NULL Data->Thread in Read PreOp?

Hello, I just got a crash dump from the field and I’m looking at it and it looks like I’m getting a NULL Data->Thread in my Read PreOp.

At the bottom is an analyze-v and maybe I’m misreading it but here is my thinking:
the exception is happening at 80832285 (nt!PsGetThreadProcess+0x00000008)

nt!IoThreadToProcess:
8083227d 8bff mov edi,edi
8083227f 55 push ebp
80832280 8bec mov ebp,esp
80832282 8b4508 mov eax,dword ptr [ebp+8]
80832285 8b8018020000 mov eax,dword ptr [eax+218h] ds:0023:00000218=00000000
8083228b 5d pop ebp
8083228c c20400 ret 4

and the source code looks like this:
FLT_PREOP_CALLBACK_STATUS PreReadWrite(IN OUT PFLT_CALLBACK_DATA Data, IN PCFLT_RELATED_OBJECTS FltObjects, OUT PVOID *CompletionContext)
{
NTSTATUS status;
BOOLEAN bDenyAccess;
PFILE_OBJECT pFileInfo;
SIDENTRY * pSidEntry;
BOOLEAN bRedirect;
WCHAR * pszRedirectTo;
BOOLEAN bInteresting;

pszRedirectTo = NULL;

pFileInfo = FltObjects->FileObject;
pSidEntry = NULL;

// Whatever is being done, see if it is being done by our user process and allow it if it is.
if (IoThreadToProcess(Data->Thread ) == IFSData.UserProcess)
return FLT_PREOP_SUCCESS_NO_CALLBACK;

But for THIS to be true, that would mean that the Thread member of Data would be NULL.
and while I can test for this condition, I didn’t occur to me that that would ever happen.

So I guess my question is this…am I reading this correctly?

thank you,

Gene

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

SYSTEM_THREAD_EXCEPTION_NOT_HANDLED_M (1000007e)
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.
Some common problems are exception code 0x80000003. This means a hard
coded breakpoint or assertion was hit, but this system was booted
/NODEBUG. This is not supposed to happen as developers should never have
hardcoded breakpoints in retail code, but …
If this happens, make sure a debugger gets connected, and the
system is booted /DEBUG. This will let us see why this breakpoint is
happening.
Arguments:
Arg1: c0000005, The exception code that was not handled
Arg2: 80832285, The address that the exception occurred at
Arg3: f78e2b48, Exception Record Address
Arg4: f78e2844, 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!PsGetThreadProcess+8
80832285 8b8018020000 mov eax,dword ptr [eax+218h]

EXCEPTION_RECORD: f78e2b48 – (.exr 0xfffffffff78e2b48)
ExceptionAddress: 80832285 (nt!PsGetThreadProcess+0x00000008)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 00000000
Parameter[1]: 00000218
Attempt to read from address 00000218

CONTEXT: f78e2844 – (.cxr 0xfffffffff78e2844)
eax=00000000 ebx=89077914 ecx=8837e8e8 edx=00000000 esi=8837e8e8 edi=f78e2c4c
eip=80832285 esp=f78e2c10 ebp=f78e2c10 iopl=0 nv up ei pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010246
nt!PsGetThreadProcess+0x8:
80832285 8b8018020000 mov eax,dword ptr [eax+218h] ds:0023:00000218=00000000
Resetting default scope

CUSTOMER_CRASH_COUNT: 1

DEFAULT_BUCKET_ID: NULL_CLASS_PTR_DEREFERENCE

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: 00000218

BUGCHECK_STR: 0x7E

EXCEPTION_STR: 0x0

LAST_CONTROL_TRANSFER: from b9526607 to 80832285

STACK_TEXT:
f78e2c10 b9526607 00000000 8865974c 886595d8 nt!PsGetThreadProcess+0x8
f78e2c2c f73014e8 89077914 f78e2c4c f78e2c68 SoxAudit!PreReadWrite+0x1b [c:\development\main\filemaster\bssaudit\filter\bssaudit.c @ 2527]
f78e2c8c f7302f48 008e2cd4 00000000 f78e2cd4 fltmgr!FltpPerformPreCallbacks+0x2d4
f78e2ca0 f73038f0 f78e2cd4 00000000 8923d448 fltmgr!FltpPassThroughInternal+0x32
f78e2cbc f7303cf1 f78e2c01 8837e8e8 89f54b58 fltmgr!FltpPassThrough+0x1c2
f78e2cec 80828c95 8923d448 8861c990 8861cbb0 fltmgr!FltpDispatch+0x10d
f78e2d00 ba50869a 8970b270 88e91548 f78e2d40 nt!IofCallDriver+0x45
f78e2d14 ba51c831 8923d448 00000000 8970b278 afd!AfdMdlReadComplete+0xb2
f78e2d38 ba51d59a 890108b0 ba51d59a 8856a988 afd!AfdCleanupPacketChain+0x9e
f78e2d80 808203bd 0056a988 00000000 89f98020 afd!AfdCompleteTPackets+0x7f
f78e2dac 80905d2c 8856a988 00000000 00000000 nt!ExpWorkerThread+0xeb
f78e2ddc 80828499 80820300 00000001 00000000 nt!PspSystemThreadStartup+0x2e
00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x16

FOLLOWUP_IP:
SoxAudit!PreReadWrite+1b [c:\development\main\filemaster\bssaudit\filter\bssaudit.c @ 2527]
b9526607 3b050c7552b9 cmp eax,dword ptr [SoxAudit!IFSData+0xc (b952750c)]

FAULTING_SOURCE_CODE:
2523: pFileInfo = FltObjects->FileObject;
2524: pSidEntry = NULL;
2525:
2526: // Whatever is being done, see if it is being done by our user process and allow it if it is.

2527: if (IoThreadToProcess(Data->Thread ) == IFSData.UserProcess)
2528: return FLT_PREOP_SUCCESS_NO_CALLBACK;
2529:
2530: // return FLT_PREOP_SUCCESS_NO_CALLBACK; // works here
2531:
2532: #ifdef _WIN64

SYMBOL_STACK_INDEX: 1

SYMBOL_NAME: SoxAudit!PreReadWrite+1b

FOLLOWUP_NAME: MachineOwner

MODULE_NAME: SoxAudit

IMAGE_NAME: SoxAudit.sys

DEBUG_FLR_IMAGE_TIMESTAMP: 4904e7e1

STACK_COMMAND: .cxr 0xfffffffff78e2844 ; kb

FAILURE_BUCKET_ID: 0x7E_SoxAudit!PreReadWrite+1b

BUCKET_ID: 0x7E_SoxAudit!PreReadWrite+1b

Followup: MachineOwner

Could the problem be that I’m not checking the Flags to make sure that FLTFL_CALLBACK_DATA_FS_FILTER_OPERATION is set? I figured that a mini filter would never get non-mini filter operations.

kd> ?? Data
struct _FLT_CALLBACK_DATA * 0x89077914
+0x000 Flags : 1
+0x004 Thread : (null)
+0x008 Iopb : 0x89077940 _FLT_IO_PARAMETER_BLOCK
+0x00c IoStatus : _IO_STATUS_BLOCK
+0x014 TagData : (null)
+0x018 QueueLinks : _LIST_ENTRY [0x0 - 0x0]
+0x020 QueueContext : [2] (null)
+0x018 FilterContext : [4] (null)
+0x028 RequestorMode : 0 ‘’

Hi Gene,

FS_FILTER is one IO type, like IRP and FastIO and you get all three of them in a minifilter. The thread in the FS_FILTER and FastIo cases comes from PsGetCurrentThread() because they are synchronous and in the irp case from the Irp itself (look at Tail.Overlay.Thread at the IRP MSDN article here: http://msdn.microsoft.com/en-us/library/aa491631.aspx).

I remember I’ve seen cases where it’s NULL but I can’t remember when I happened. Can you look at the Irp ? Maybe it’s not properly initialized.

Regards,
Alex.
This posting is provided “AS IS” with no warranties, and confers no rights.

Thanks Alex,

Since you’ve seen it before, I’ll handle the condition at the start of all my callbacks. I poked around trying to find the IRP structure but didn’t have any luck.

If you can point me to how to get to the IRP structure from the MiniFilter pre-read callback, I’ll try to find it in the minidump.

thanks again,

Gene

Hi Gene,

Well, what I usually do to find the associated IRP is go up the call stack for a function that receives an IRP as a parameter or use !thread and see if there is an IRP there. Anyhow, if you can work around the issue of receiving a NULL thread then that’s prefect.

Regards,
Alex.
This posting is provided “AS IS” with no warranties, and confers no rights.

Oh, and of course I forgot about the most useful one: !fltkd.cbd should print the IRP as well given a callback data.

Regards,
Alex.
This posting is provided “AS IS” with no warranties, and confers no rights.