From 5d33bdc236a6dcde0d4f177c3ccf268240bf4e98 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Wed, 24 Jun 2009 21:57:48 +0000 Subject: [PATCH] - Fix a crash that happens when we are running at APC_LEVEL, acquire the recursive mutex (which improperly handled APC_LEVEL), then attempt to access paged pool (or do anything else that depends on Irql < DISPATCH_LEVEL) - Optimize the code for acquiring and releasing the recursive mutex at DISPATCH_LEVEL svn path=/trunk/; revision=41600 --- .../drivers/network/tcpip/recmutex/recmutex.c | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/reactos/drivers/network/tcpip/recmutex/recmutex.c b/reactos/drivers/network/tcpip/recmutex/recmutex.c index 0427a29664b..5951045cb3c 100644 --- a/reactos/drivers/network/tcpip/recmutex/recmutex.c +++ b/reactos/drivers/network/tcpip/recmutex/recmutex.c @@ -14,6 +14,7 @@ VOID RecursiveMutexInit( PRECURSIVE_MUTEX RecMutex ) { SIZE_T RecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex, BOOLEAN ToWrite ) { NTSTATUS Status = STATUS_SUCCESS; PVOID CurrentThread = KeGetCurrentThread(); + KIRQL CurrentIrql; /* Wait for the previous user to unlock the RecMutex state. There might be * multiple waiters waiting to change the state. We need to check each @@ -27,9 +28,13 @@ SIZE_T RecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex, BOOLEAN ToWrite ) { return TRUE; } - if( KeGetCurrentIrql() == PASSIVE_LEVEL ) { + CurrentIrql = KeGetCurrentIrql(); + + ASSERT(CurrentIrql <= DISPATCH_LEVEL); + + if( CurrentIrql <= APC_LEVEL ) { ExAcquireFastMutex( &RecMutex->Mutex ); - RecMutex->OldIrql = PASSIVE_LEVEL; + RecMutex->OldIrql = CurrentIrql; while( RecMutex->Locked ) { ExReleaseFastMutex( &RecMutex->Mutex ); Status = KeWaitForSingleObject( &RecMutex->StateLockedEvent, @@ -45,7 +50,8 @@ SIZE_T RecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex, BOOLEAN ToWrite ) { RecMutex->LockCount++; ExReleaseFastMutex( &RecMutex->Mutex ); } else { - KeAcquireSpinLock( &RecMutex->SpinLock, &RecMutex->OldIrql ); + KeAcquireSpinLockAtDpcLevel( &RecMutex->SpinLock ); + RecMutex->OldIrql = DISPATCH_LEVEL; RecMutex->Locked = TRUE; RecMutex->Writer = ToWrite; RecMutex->CurrentThread = CurrentThread; @@ -56,14 +62,13 @@ SIZE_T RecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex, BOOLEAN ToWrite ) { } VOID RecursiveMutexLeave( PRECURSIVE_MUTEX RecMutex ) { - if( RecMutex->LockCount == 0 ) { - return; - } else - RecMutex->LockCount--; + + ASSERT(RecMutex->LockCount > 0); + RecMutex->LockCount--; if( !RecMutex->LockCount ) { RecMutex->CurrentThread = NULL; - if( RecMutex->OldIrql == PASSIVE_LEVEL ) { + if( RecMutex->OldIrql <= APC_LEVEL ) { ExAcquireFastMutex( &RecMutex->Mutex ); RecMutex->Locked = FALSE; RecMutex->Writer = FALSE; @@ -71,10 +76,9 @@ VOID RecursiveMutexLeave( PRECURSIVE_MUTEX RecMutex ) { } else { RecMutex->Locked = FALSE; RecMutex->Writer = FALSE; - KeReleaseSpinLock( &RecMutex->SpinLock, RecMutex->OldIrql ); + KeReleaseSpinLockFromDpcLevel( &RecMutex->SpinLock ); } - RecMutex->OldIrql = PASSIVE_LEVEL; KePulseEvent( &RecMutex->StateLockedEvent, IO_NETWORK_INCREMENT, FALSE ); }