FltGetFileContext cause bsod in filter pre operation callback (IRP_MJ_READ)

Sometimes function FltGetFileContext is crashed with bsod. FltGetFileContext is called also in pre-write and pre-cleanup callbacks. But I didn’t observe crashes here.

Callstack:
nt!KeBugCheckEx+0x107
nt!ExAcquirePushLockSharedEx+0x142
nt!FsRtlLookupPerFileContext+0x6a
FLTMGR!FltpLookupPerFileContext+0x3d
FLTMGR!FltpGetFileListCtrl+0x55
FLTMGR!FltGetFileContext+0x2a
FsFilter!FilePostRead+0xc5
FLTMGR!FltpPerformPostCallbacksWorker+0x347

BSOD happens only here:
`FLT_POSTOP_CALLBACK_STATUS FilePostRead
(
Inout PFLT_CALLBACK_DATA Data,
In PCFLT_RELATED_OBJECTS FltObjects,
In_opt PVOID CompletionContext,
In FLT_POST_OPERATION_FLAGS Flags
)
{
(void)Flags;
(void)CompletionContext;
NTSTATUS status = Data->IoStatus.Status;
if (!NT_SUCCESS(status))
{
return FLT_POSTOP_FINISHED_PROCESSING;
}

ULONG processId = FltGetRequestorProcessId(Data);
FLT_IO_PARAMETER_BLOCK* params = Data->Iopb;
void* readBuffer = NULL;
if (params->Parameters.Read.MdlAddress != NULL)
{
    readBuffer = MmGetSystemAddressForMdlSafe(params->Parameters.Read.MdlAddress, NormalPagePriority);
}
else if (params->Parameters.Read.ReadBuffer != NULL)
{
    readBuffer = params->Parameters.Read.ReadBuffer;
}
else
{
    return FLT_POSTOP_FINISHED_PROCESSING;
}

PFLT_CONTEXT fctx = NULL;
status = FltGetFileContext(FltObjects->Instance, FltObjects->FileObject, &fctx); //bsod occurs only here


`

Where I need to dig to find the reason?

You haven’t supplied enough information (like what does analyze -v or given enough stack, but I’d SWAG that IRQL is an issue and your context is paged.

Ok. Crash analyze in attached file.
Context in allocated in nonpaged pool.
`PFLT_CONTEXT fctx = NULL;
status = FltAllocateContext(g_data.Filter, FLT_FILE_CONTEXT, sizeof(UINT64), NonPagedPool, &fctx);
if (NT_SUCCESS(status) && (fctx != NULL))
{
((ULONG64)fctx) = uid++;
status = FltSetFileContext(FltObjects->Instance, FltObjects->FileObject, FLT_SET_CONTEXT_REPLACE_IF_EXISTS, fctx,
if (!NT_SUCCESS(

DbgPrint(“FPsCreate FltSetFileContext %X\n”, status);
return FLT_POSTOP_FINISHED_PROCESSING;
}
}
else
{
DbgPrint(“FPsC cc %X\n”, status);
return FLT_POSTOP_FINISHED_PROCESSING;
}`

Well that’s a cute stack.

This looks like something very weird in DPC chaining (since when did FsRtlAcquireToCreateMappedSection provoke a IO completion?).

I’m much happier at low IRQL so perhaps some of the more device oriented readers can help because from where I’m sitting this makes your driver look like attritional damage.

FltGetFileContext requires IRQL < DISPATCH_LEVEL but your PostRead can run at IRQL <= DISPATCH_LEVEL. If you need your file context in Post you need to get it in Pre and pass it via your completion context.

1 Like

@“Scott_Noone_(OSR)” said:
FltGetFileContext requires IRQL < DISPATCH_LEVEL but your PostRead can run at IRQL <= DISPATCH_LEVEL. If you need your file context in Post you need to get it in Pre and pass it via your completion context.

Thank you Scott,
This is the root of problem.
But there is a question about FltGetFileNameInformation. It can be call from same level. But it works well in post create callback. What the difference between IRP_IMJ_CREATE and
IRP_IMJ_READ regarding level?

The documentation does a poor job clarifying IRQL rules around Pre/Post operation callbacks. Documenting this is on my prioritized list of things to do (which is around here someplace…I think the last time I saw it was March :)).

FltMgr guarantees that PostCreate will be called at PASSIVE_LEVEL and in the same context as PreCreate. The documentation confirms that here:

Post-create callback routines are called at IRQL = PASSIVE_LEVEL, in the context of the thread that originated the IRP_MJ_CREATE operation.

No such guarantee is made for PostRead/PostWrite (which are the ones most likely to execute at IRQL DISPATCH_LEVEL).

1 Like