fixed apc leak :DDD

This commit is contained in:
lhodges1 2023-09-26 23:32:06 +10:00
parent 861c6d84f8
commit 48799fe6d9
5 changed files with 133 additions and 89 deletions

View file

@ -33,13 +33,21 @@ unlock:
KeReleaseGuardedMutex( &driver_config.lock );
}
/*
* No need to hold the lock here as it thread freeing the APCs will
* already hold the configuration lock. We also dont want to release and
* reclaim the lock before calling this function since we need to ensure
* we hold the lock during the entire free process.
*/
STATIC
BOOLEAN
FreeApcContextStructure(
_Inout_ PAPC_CONTEXT_HEADER Context
)
{
BOOLEAN result = FALSE;
KeAcquireGuardedMutex( &driver_config.lock );
DEBUG_LOG( "All APCs executed, freeing context structure" );
for ( INT index = 0; index < 10; index++ )
{
@ -58,10 +66,99 @@ FreeApcContextStructure(
}
unlock:
KeReleaseGuardedMutex( &driver_config.lock );
return result;
}
VOID
IncrementApcCount(
_In_ LONG ContextId
)
{
PAPC_CONTEXT_HEADER header = NULL;
GetApcContext( &header, ContextId );
if ( !header )
return;
KeAcquireGuardedMutex( &driver_config.lock );
header->count += 1;
KeReleaseGuardedMutex( &driver_config.lock );
}
VOID
FreeApcAndDecrementApcCount(
_In_ PRKAPC Apc,
_In_ LONG ContextId
)
{
PAPC_CONTEXT_HEADER context = NULL;
ExFreePoolWithTag( Apc, POOL_TAG_APC );
GetApcContext( &context, ContextId );
if ( !context )
goto end;
KeAcquireGuardedMutex( &driver_config.lock );
context->count -= 1;
switch ( ContextId )
{
case APC_CONTEXT_ID_STACKWALK:
if ( context->count > 0 )
goto end;
PAPC_STACKWALK_CONTEXT stackwalk_context = ( PAPC_STACKWALK_CONTEXT )context;
FreeApcStackwalkApcContextInformation( stackwalk_context );
FreeApcContextStructure( stackwalk_context );
break;
}
end:
KeReleaseGuardedMutex( &driver_config.lock );
}
//NTSTATUS
//QueryActiveApcContextsForCompletion()
//{
// DEBUG_LOG( "Querying active apc contexts" );
//
// KeAcquireGuardedMutex( &driver_config.lock );
//
// for ( INT index = 0; index < 10; index++ )
// {
// PAPC_CONTEXT_HEADER entry = NULL;
// GetApcContextByIndex( &entry, index );
//
// /* ensure we dont try to unlock a null entry */
// if ( entry == NULL )
// continue;
//
// DEBUG_LOG( "APC Context id: %lx", entry->context_id );
// DEBUG_LOG( "Actice Apc Count: %i", entry->count );
//
// if ( entry->count > 0 )
// goto end;
//
// switch ( entry->context_id )
// {
// case APC_CONTEXT_ID_STACKWALK:
// FreeApcStackwalkApcContextInformation( entry );
// FreeApcContextStructure( entry );
// break;
// }
// }
//end:
//
// KeReleaseGuardedMutex( &driver_config.lock );
// return STATUS_SUCCESS;
//}
VOID
InsertApcContext(
_In_ PVOID Context
@ -460,6 +557,7 @@ DriverUnload(
)
{
//PsSetCreateProcessNotifyRoutine( ProcessCreateNotifyRoutine, TRUE );
//QueryActiveApcContextsForCompletion();
FreeAllApcContextStructures();
CleanupDriverConfigOnUnload();
IoDeleteDevice( DriverObject->DeviceObject );

View file

@ -112,8 +112,24 @@ GetApcContextByIndex(
_In_ INT Index
);
VOID
IncrementApcCount(
_In_ LONG ContextId
);
VOID
FreeApcAndDecrementApcCount(
_In_ PRKAPC Apc,
_In_ LONG ContextId
);
VOID TerminateProtectedProcessOnViolation();
VOID ClearProcessConfigOnProcessTermination();
NTSTATUS
QueryActiveApcContextForCompletion(
_In_ LONG ContextId
);
#endif

View file

@ -124,11 +124,6 @@ NTSTATUS DeviceControl(
case IOCTL_HANDLE_REPORTS_IN_CALLBACK_QUEUE:
status = QueryActiveApcContextsForCompletion();
if ( !NT_SUCCESS( status ) )
DEBUG_ERROR( "QueryActiveApcContextsForCompletion failed with status %x", status );
status = HandlePeriodicGlobalReportQueueQuery(Irp);
if ( !NT_SUCCESS( status ) )

View file

@ -902,27 +902,7 @@ ApcRundownRoutine(
_In_ PRKAPC Apc
)
{
//FreeApcAndStatusStructure( Apc, APC_CONTEXT_ID_STACKWALK );
}
STATIC
VOID
FreeApcAndDecrementApcCount(
_In_ PRKAPC Apc,
_In_ LONG ContextId
)
{
PAPC_CONTEXT_HEADER header = NULL;
ExFreePoolWithTag( Apc, POOL_TAG_APC );
GetApcContext( &header, ContextId );
if ( !header )
return;
KeAcquireGuardedMutex( &header->lock );
header->count -= 1;
KeReleaseGuardedMutex( &header->lock );
FreeApcAndDecrementApcCount( Apc, APC_CONTEXT_ID_STACKWALK );
}
/*
@ -951,7 +931,7 @@ ApcKernelRoutine(
buffer = ExAllocatePool2( POOL_FLAG_NON_PAGED, 0x200, POOL_TAG_APC );
if ( !buffer )
return;
goto free;
frames_captured = RtlCaptureStackBackTrace(
NULL,
@ -986,7 +966,9 @@ ApcKernelRoutine(
free:
ExFreePoolWithTag( buffer, POOL_TAG_APC );
if (buffer )
ExFreePoolWithTag( buffer, POOL_TAG_APC );
FreeApcAndDecrementApcCount( Apc, APC_CONTEXT_ID_STACKWALK );
}
@ -1004,23 +986,6 @@ ApcNormalRoutine(
}
STATIC
VOID
IncrementApcCount(
_In_ LONG ContextId
)
{
PAPC_CONTEXT_HEADER header = NULL;
GetApcContext( &header, ContextId );
if ( !header )
return;
KeAcquireGuardedMutex( &header->lock );
header->count += 1;
KeReleaseGuardedMutex( &header->lock );
}
STATIC
VOID
ValidateThreadViaKernelApcCallback(
@ -1035,6 +1000,8 @@ ValidateThreadViaKernelApcCallback(
PKAPC apc = NULL;
BOOLEAN apc_status;
HANDLE id = PsGetProcessId( Process );
/* we dont want to schedule an apc to threads owned by the kernel */
if ( Process == PsInitialSystemProcess )
return;
@ -1109,8 +1076,6 @@ ValidateThreadsViaKernelApc()
context->header.context_id = APC_CONTEXT_ID_STACKWALK;
context->modules = ExAllocatePool2( POOL_FLAG_NON_PAGED, sizeof( SYSTEM_MODULES ), POOL_TAG_APC );
KeInitializeGuardedMutex( &context->header.lock );
if ( !context->modules )
{
ExFreePoolWithTag( context, POOL_TAG_APC );
@ -1139,40 +1104,8 @@ FreeApcStackwalkApcContextInformation(
_In_ PAPC_STACKWALK_CONTEXT Context
)
{
if (Context->modules->address )
ExFreePoolWithTag( Context->modules->address, SYSTEM_MODULES_POOL );
if ( Context->modules )
ExFreePoolWithTag( Context->modules, SYSTEM_MODULES_POOL );
}
NTSTATUS
QueryActiveApcContextsForCompletion()
{
for ( INT index = 0; index < 10; index++ )
{
PAPC_CONTEXT_HEADER entry = NULL;
GetApcContextByIndex( &entry, index );
/* ensure we dont try to unlock a null entry */
if ( entry == NULL )
continue;
KeAcquireGuardedMutex( &entry->lock );
DEBUG_LOG( "APC Context id: %lx", entry->context_id );
DEBUG_LOG( "Actice Apc Count: %i", entry->count );
if ( entry->count > 0 )
goto unlock;
switch ( entry->context_id )
{
case APC_CONTEXT_ID_STACKWALK:
FreeApcStackwalkApcContextInformation( entry);
break;
}
unlock:
KeReleaseGuardedMutex( &entry->lock );
}
return STATUS_SUCCESS;
ExFreePoolWithTag( Context->modules, POOL_TAG_APC );
}

View file

@ -102,7 +102,6 @@ typedef struct _APC_CONTEXT_HEADER
{
LONG context_id;
volatile INT count;
KGUARDED_MUTEX lock;
}APC_CONTEXT_HEADER, * PAPC_CONTEXT_HEADER;
@ -130,13 +129,16 @@ NTSTATUS HandleNmiIOCTL(
_In_ PIRP Irp
);
VOID FreeApcContextStructure(
_Inout_ PVOID Context
BOOLEAN
FreeApcContextStructure(
_Inout_ PAPC_CONTEXT_HEADER Context
);
NTSTATUS ValidateThreadsViaKernelApc();
NTSTATUS
QueryActiveApcContextsForCompletion();
VOID
FreeApcStackwalkApcContextInformation(
_In_ PAPC_STACKWALK_CONTEXT Context
);
#endif