Author: rmessiant
Date: Sun May 29 22:29:10 2011
New Revision: 52002
URL:
http://svn.reactos.org/svn/reactos?rev=52002&view=rev
Log:
[NTOSKRNL]
- Simplify remove lock tracking block list handling.
- Correct check for unlimited locking time being allowed.
- Eliminate use-after-free after removing a tracking block.
Modified:
trunk/reactos/ntoskrnl/io/iomgr/remlock.c
Modified: trunk/reactos/ntoskrnl/io/iomgr/remlock.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/remlock.…
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/remlock.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/remlock.c [iso-8859-1] Sun May 29 22:29:10 2011
@@ -16,7 +16,7 @@
typedef struct _IO_REMOVE_LOCK_TRACKING_BLOCK
{
- SINGLE_LIST_ENTRY BlockEntry;
+ PIO_REMOVE_LOCK_TRACKING_BLOCK Next;
PVOID Tag;
LARGE_INTEGER LockMoment;
LPCSTR File;
@@ -114,7 +114,8 @@
/* Queue the block */
KeAcquireSpinLock(&(Lock->Dbg.Spin), &OldIrql);
- PushEntryList((PSINGLE_LIST_ENTRY)&(Lock->Dbg.Blocks),
&(TrackingBlock->BlockEntry));
+ TrackingBlock->Next = Lock->Dbg.Blocks;
+ Lock->Dbg.Blocks = TrackingBlock;
KeReleaseSpinLock(&(Lock->Dbg.Spin), OldIrql);
}
}
@@ -149,8 +150,8 @@
LONG LockValue;
BOOLEAN TagFound;
LARGE_INTEGER CurrentMoment;
- PSINGLE_LIST_ENTRY ListEntry;
PIO_REMOVE_LOCK_TRACKING_BLOCK TrackingBlock;
+ PIO_REMOVE_LOCK_TRACKING_BLOCK *TrackingBlockLink;
PEXTENDED_IO_REMOVE_LOCK Lock = (PEXTENDED_IO_REMOVE_LOCK)RemoveLock;
/* Check what kind of lock this is */
@@ -164,12 +165,12 @@
/* Start browsing tracking blocks to find a block that would match given tag */
TagFound = FALSE;
- for (ListEntry = ((PSINGLE_LIST_ENTRY)&Lock->Dbg.Blocks)->Next;
ListEntry; ListEntry = ListEntry->Next)
- {
- TrackingBlock = CONTAINING_RECORD(ListEntry, IO_REMOVE_LOCK_TRACKING_BLOCK,
BlockEntry);
-
+ TrackingBlock = Lock->Dbg.Blocks;
+ TrackingBlockLink = &(Lock->Dbg.Blocks);
+ while (TrackingBlock != NULL)
+ {
/* First of all, check if the lock was locked for too long */
- if (CurrentMoment.QuadPart &&
+ if (TrackingBlock->LockMoment.QuadPart &&
CurrentMoment.QuadPart - TrackingBlock->LockMoment.QuadPart >
Lock->Dbg.MaxLockedTicks)
{
DPRINT("Lock %#08lx (with tag %#08lx) was supposed to be held at max
%I64d ticks but lasted longer\n",
@@ -178,29 +179,23 @@
ASSERT(FALSE);
}
- /* If no tracking was found yet */
- if (TagFound == FALSE)
- {
- /* Check if the current one could match */
- if (TrackingBlock->Tag == Tag)
- {
- /* Yes, then remove it from the queue and free it */
- TagFound = TRUE;
- if (ListEntry ==
((PSINGLE_LIST_ENTRY)&Lock->Dbg.Blocks)->Next)
- {
- /* Here it is head, remove it using macro */
- PopEntryList((PSINGLE_LIST_ENTRY)&(Lock->Dbg.Blocks));
- ExFreePoolWithTag(TrackingBlock, Lock->Dbg.AllocateTag);
- }
- else
- {
- /* It's not head, remove it "manually */
- ListEntry->Next = TrackingBlock->BlockEntry.Next;
- ExFreePoolWithTag(TrackingBlock, Lock->Dbg.AllocateTag);
- }
- }
- }
- }
+ /* Check if this is the first matching tracking block */
+ if ((TagFound == FALSE) && (TrackingBlock->Tag == Tag))
+ {
+ /* Unlink this tracking block, and free it */
+ TagFound = TRUE;
+ *TrackingBlockLink = TrackingBlock->Next;
+ ExFreePoolWithTag(TrackingBlock, Lock->Dbg.AllocateTag);
+ TrackingBlock = *TrackingBlockLink;
+ }
+ else
+ {
+ /* Go to the next tracking block */
+ TrackingBlockLink = &(TrackingBlock->Next);
+ TrackingBlock = TrackingBlock->Next;
+ }
+ }
+
/* We're done, release queue lock */
KeReleaseSpinLock(&(Lock->Dbg.Spin), OldIrql);
@@ -271,7 +266,7 @@
ASSERT(Lock->Dbg.Blocks);
/* Get it */
- TrackingBlock = CONTAINING_RECORD(Lock->Dbg.Blocks,
IO_REMOVE_LOCK_TRACKING_BLOCK, BlockEntry);
+ TrackingBlock = Lock->Dbg.Blocks;
/* Tag should match */
if (TrackingBlock->Tag != Tag)
{