Does anyone know what types of synchronization objects fall under the purview of this bugcheck code? I would guess KMUTEX and FAST_MUTEX but my driver does not use those directly. We use EX_PUSH_LOCK and ERESOURCE.
I did some testing and SYSTEM_EXIT_OWNED_MUTEX is only caused by KMUTEX.
FAST_MUTEXT result in WORKER_THREAD_RETURNED_AT_BAD_IRQL.
Critical/Guarded Regions and Pushlocks result in APC_INDEX_MISMATCH.
Failure to release an ERESOURCE goes undetected by the OS. Perhaps this is by design.
typedef struct _WORKER_CONTEXT
{
PWORK_QUEUE_ITEM pWorkItem;
KEVENT Event;
} WORKER_CONTEXT, *PWORKER_CONTEXT;
VOID Worker(IN PVOID Parameter)
{
PAGED_CODE();
PWORKER_CONTEXT pContext = (PWORKER_CONTEXT) Parameter;
// Comment out lines with bucheck codes to cause those violations
//
// Mutex
//
KMUTEX mutex;
KeInitializeMutex(&mutex, 0);
NTSTATUS ntStatus = KeWaitForMutexObject(&mutex, Executive, KernelMode, FALSE, NULL);
CFIX_ASSERT_STATUS(ntStatus, STATUS_SUCCESS);
KeReleaseMutex(&mutex, FALSE); // SYSTEM_EXIT_OWNED_MUTEX
//
// Fast Mutex
//
FAST_MUTEX fastMutex;
ExInitializeFastMutex(&fastMutex);
ExAcquireFastMutex(&fastMutex);
ExReleaseFastMutex(&fastMutex); // WORKER_THREAD_RETURNED_AT_BAD_IRQL
//
// Fast Mutex Unsafe
//
KeEnterCriticalRegion();
ExAcquireFastMutexUnsafe(&fastMutex);
ExReleaseFastMutexUnsafe(&fastMutex);
KeLeaveCriticalRegion(); // APC_INDEX_MISMATCH
//
// ERESOURCE
//
ERESOURCE resource;
ExInitializeResourceLite(&resource);
ExAcquireResourceExclusiveLite(&resource, TRUE);
ExReleaseResourceLite(&resource);
ExDeleteResourceLite(&resource);
//
// Pushlock
//
EX_PUSH_LOCK pushlock;
FltInitializePushLock(&pushlock);
FltAcquirePushLockExclusive(&pushlock);
FltReleasePushLock(&pushlock); // APC_INDEX_MISMATCH
FltDeletePushLock(&pushlock);
KeSetEvent(&pContext->Event, 0, FALSE);
}
static void __stdcall TestBugcheck()
{
PWORKER_CONTEXT pContext = (PWORKER_CONTEXT) ExAllocatePoolWithTag(NonPagedPool, sizeof(WORKER_CONTEXT), ‘XIFC’);
CFIX_ASSERT(pContext);
pContext->pWorkItem = (PWORK_QUEUE_ITEM) ExAllocatePoolWithTag(NonPagedPool, sizeof(WORK_QUEUE_ITEM), ‘XIFC’);
CFIX_ASSERT(pContext->pWorkItem);
KeInitializeEvent(&pContext->Event, NotificationEvent, FALSE);
ExInitializeWorkItem(pContext->pWorkItem, Worker, pContext);
ExQueueWorkItem(pContext->pWorkItem, DelayedWorkQueue);
NTSTATUS ntStatus = KeWaitForSingleObject(&pContext->Event, Executive, KernelMode, FALSE, NULL);
CFIX_ASSERT_STATUS(ntStatus, STATUS_SUCCESS);
ExFreePool(pContext->pWorkItem);
ExFreePool(pContext);
}
You must acquire/release an ERESOURCE within a critical region, so failure
to release one also usually ends up as an APC_INDEX_MISMATCH. However, if
you fail to release the ERESOURCE but DO leave the critical region then this
will generally go unnoticed (until someone else tries to acquire the lock
and waits forever).
-scott
OSR
@OSRDrivers
wrote in message news:xxxxx@windbg…
I did some testing and SYSTEM_EXIT_OWNED_MUTEX is only caused by KMUTEX.
FAST_MUTEXT result in WORKER_THREAD_RETURNED_AT_BAD_IRQL.
Critical/Guarded Regions and Pushlocks result in APC_INDEX_MISMATCH.
Failure to release an ERESOURCE goes undetected by the OS. Perhaps this is
by design.
typedef struct _WORKER_CONTEXT
{
PWORK_QUEUE_ITEM pWorkItem;
KEVENT Event;
} WORKER_CONTEXT, *PWORKER_CONTEXT;
VOID Worker(IN PVOID Parameter)
{
PAGED_CODE();
PWORKER_CONTEXT pContext = (PWORKER_CONTEXT) Parameter;
// Comment out lines with bucheck codes to cause those violations
//
// Mutex
//
KMUTEX mutex;
KeInitializeMutex(&mutex, 0);
NTSTATUS ntStatus = KeWaitForMutexObject(&mutex, Executive, KernelMode,
FALSE, NULL);
CFIX_ASSERT_STATUS(ntStatus, STATUS_SUCCESS);
KeReleaseMutex(&mutex, FALSE); // SYSTEM_EXIT_OWNED_MUTEX
//
// Fast Mutex
//
FAST_MUTEX fastMutex;
ExInitializeFastMutex(&fastMutex);
ExAcquireFastMutex(&fastMutex);
ExReleaseFastMutex(&fastMutex); // WORKER_THREAD_RETURNED_AT_BAD_IRQL
//
// Fast Mutex Unsafe
//
KeEnterCriticalRegion();
ExAcquireFastMutexUnsafe(&fastMutex);
ExReleaseFastMutexUnsafe(&fastMutex);
KeLeaveCriticalRegion(); // APC_INDEX_MISMATCH
//
// ERESOURCE
//
ERESOURCE resource;
ExInitializeResourceLite(&resource);
ExAcquireResourceExclusiveLite(&resource, TRUE);
ExReleaseResourceLite(&resource);
ExDeleteResourceLite(&resource);
//
// Pushlock
//
EX_PUSH_LOCK pushlock;
FltInitializePushLock(&pushlock);
FltAcquirePushLockExclusive(&pushlock);
FltReleasePushLock(&pushlock); // APC_INDEX_MISMATCH
FltDeletePushLock(&pushlock);
KeSetEvent(&pContext->Event, 0, FALSE);
}
static void __stdcall TestBugcheck()
{
PWORKER_CONTEXT pContext = (PWORKER_CONTEXT)
ExAllocatePoolWithTag(NonPagedPool, sizeof(WORKER_CONTEXT), ‘XIFC’);
CFIX_ASSERT(pContext);
pContext->pWorkItem = (PWORK_QUEUE_ITEM)
ExAllocatePoolWithTag(NonPagedPool, sizeof(WORK_QUEUE_ITEM), ‘XIFC’);
CFIX_ASSERT(pContext->pWorkItem);
KeInitializeEvent(&pContext->Event, NotificationEvent, FALSE);
ExInitializeWorkItem(pContext->pWorkItem, Worker, pContext);
ExQueueWorkItem(pContext->pWorkItem, DelayedWorkQueue);
NTSTATUS ntStatus = KeWaitForSingleObject(&pContext->Event, Executive,
KernelMode, FALSE, NULL);
CFIX_ASSERT_STATUS(ntStatus, STATUS_SUCCESS);
ExFreePool(pContext->pWorkItem);
ExFreePool(pContext);
}