SYSTEM_EXIT_OWNED_MUTEX

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);
}