Minifilter hangs on unload : 0

It’s for sure got something to do with the way I manage contexts , struggling to spot it

I call FltAllocateContext in post create and if successful , save it in a custom list using the following function

{
	AutoLock<Mutex> locker(ContextsListMutex);
	PContextToDelete New = (PContextToDelete)ExAllocatePoolWithTag(NonPagedPool, sizeof(ContextToDelete), TAG);
	if (!New)
		return false;
	New->Context = (DWORD64)context;
	New->Next = nullptr;
	if (!ContextsToDelete)
	{
		ContextsToDelete = New;
		return true;
	}
	PContextToDelete current = ContextsToDelete;
	while (current->Next != nullptr)
	{
		current = (PContextToDelete)current->Next;
	}
	current->Next = (LIST_ENTRY*)New;

	return true;
} ```

On unload I call the following

{

	AutoLock<Mutex> locker(ContextsListMutex);
	if (ContextsToDelete)
	{
		PContextToDelete current = ContextsToDelete;
		PContextToDelete temp = nullptr;
		while (current != nullptr)
		{
			temp = current;
			current = (PContextToDelete)current->Next;
			ExFreePoolWithTag(temp, TAG);
		}
	}

} ``` 

and for every call the increments the reference count (FltGetStreamHandleContext in my case) I construct the following object :
AutoContext AutoHandleContx(HandleContx);

{
public:
	AutoContext(PFLT_CONTEXT Context) : m_context_ptr(Context) {};
	~AutoContext() { FltReleaseContext(m_context_ptr); };
private:
	PFLT_CONTEXT m_context_ptr;
}; ``` 

ideally initial reference by FltAllocateContext is dereferenced in pre / post close , for example

PreClose(
	_Inout_ PFLT_CALLBACK_DATA Data,
	_In_ PCFLT_RELATED_OBJECTS FltObjects,
	_Flt_CompletionContext_Outptr_ PVOID* CompletionContext
)
{
	pHandleContext HandleContx = nullptr;
	NTSTATUS status = FltGetStreamHandleContext(FltObjects->Instance, FltObjects->FileObject, reinterpret_cast<PFLT_CONTEXT*>(&HandleContx));
	if (!NT_SUCCESS(status))
		return FLT_PREOP_SUCCESS_NO_CALLBACK;
	
	// auto release get reference 
	AutoContext AutoHandleContxGet(HandleContx);

	// no write occured , no need to evaluate 
	if (HandleContx->FirstPreWrite)
	{
		contexts::RemoveContextFromList(HandleContx);
		ExFreePoolWithTag(HandleContx->FileName.Buffer, TAG);
		FltReleaseContext(HandleContx);
		return FLT_PREOP_SUCCESS_NO_CALLBACK;
	}
	
	// pass handle context pointer to post close 
	*CompletionContext = HandleContx;
	
	return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}

but in case the minifilter unloads before close has taken place the context is released through the list of contexts , anyone sees something I dont ?
usually it unloads cleanly but every once in a while it hangs and requires restart

And you have tested with verifier? That will tell you what you are leaking.

1 Like

Typical way to work with it is like this:

  1. Allocate context by calling FltAllocateContext() - ref count is 1.
  2. Call FltSetStreamHandleContext() - ref count is 2. And if successful you immediately call FltReleaseContext() to decrement ref count from step 1. Right now the ref count is 1 and the only one holding the reference is the System because you called FltSetStreamHandleContext().

At this point you don't need to do anything else, if you want, in PreCleanup just call FltDeleteStreamHandleContext but that is optional, the System will delete it at some point for you if file is closed.

Whenever you want to ask for the context, just get it and then release it. I usually use scoped objects. But I never needed to release any context in unload by myself.

So I suspect that in your case the problem is that you keep the ref count for the context allocation for the entire life, which is wrong, you should rely on the System which is keeping the context for you.

1 Like

I don’t keep the contexts for the entire lifetime of the driver, I release it on close.
on unload i release only contexts for files that haven’t been closed yet at the time of unloading , so it won’t hang

You are over thinking this. You really do not need to keep lists of contexts the OS will do it all for you. Just make sure that every allocate and every get (sets too under certain circumstances) is matched by a release.

That's it.

BTW: It's not just context leaks which cause hangs. Did you try running with verifier?

1 Like