Author: ros-arm-bringup Date: Fri Feb 15 00:19:30 2008 New Revision: 32365
URL: http://svn.reactos.org/svn/reactos?rev=32365&view=rev Log: Don't allow code to access the PFN database directly -- instead, always go through MiGetPfnEntry to have a controlled path. Add assertions to this function, to make sure PFN access is always valid (previous code would sometimes KEBUGCHECK(0) without a real explenation if such cases were encounted -- but developers randomly chose which functions would be protected). Also, since PFNs are 0-based, do allow Pfn == MmPageArraySize if someone is reading the last PFN on the system. Finally, protect some of the functions which were accessing the PFN entries outside the PFN list lock.
Modified: trunk/reactos/config.template.rbuild trunk/reactos/ntoskrnl/mm/freelist.c
Modified: trunk/reactos/config.template.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/config.template.rbuild?rev=... ============================================================================== --- trunk/reactos/config.template.rbuild (original) +++ trunk/reactos/config.template.rbuild Fri Feb 15 00:19:30 2008 @@ -45,7 +45,7 @@ <!-- Whether to compile in the integrated kernel debugger. --> -<property name="KDBG" value="1" /> +<property name="KDBG" value="0" />
<!--
Modified: trunk/reactos/ntoskrnl/mm/freelist.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/freelist.c?rev=... ============================================================================== --- trunk/reactos/ntoskrnl/mm/freelist.c (original) +++ trunk/reactos/ntoskrnl/mm/freelist.c Fri Feb 15 00:19:30 2008 @@ -50,6 +50,8 @@ PHYSICAL_PAGE, *PPHYSICAL_PAGE;
+#define ASSERT_PFN(x) ASSERT((x)->Flags.Type != 0) + /* GLOBALS ****************************************************************/
static PPHYSICAL_PAGE MmPageArray; @@ -67,6 +69,25 @@
/* FUNCTIONS *************************************************************/
+FORCEINLINE +PPHYSICAL_PAGE +MiGetPfnEntry(IN PFN_TYPE Pfn) +{ + PPHYSICAL_PAGE Page; + + /* Make sure the PFN number is valid */ + ASSERT(Pfn <= MmPageArraySize); + + /* Get the entry */ + Page = &MmPageArray[Pfn]; + + /* Make sure it's valid */ + ASSERT_PFN(Page); + + /* Return it */ + return Page; +} + PFN_TYPE NTAPI MmGetLRUFirstUserPage(VOID) @@ -83,6 +104,7 @@ return 0; } PageDescriptor = CONTAINING_RECORD(NextListEntry, PHYSICAL_PAGE, ListEntry); + ASSERT_PFN(PageDescriptor); KeReleaseSpinLock(&PageListLock, oldIrql); return PageDescriptor - MmPageArray; } @@ -92,15 +114,15 @@ MmSetLRULastPage(PFN_TYPE Pfn) { KIRQL oldIrql; - - ASSERT(Pfn < MmPageArraySize); - KeAcquireSpinLock(&PageListLock, &oldIrql); - if (MmPageArray[Pfn].Flags.Type == MM_PHYSICAL_PAGE_USED && - MmPageArray[Pfn].Flags.Consumer == MC_USER) - { - RemoveEntryList(&MmPageArray[Pfn].ListEntry); - InsertTailList(&UserPageListHead, - &MmPageArray[Pfn].ListEntry); + PPHYSICAL_PAGE Page; + + KeAcquireSpinLock(&PageListLock, &oldIrql); + Page = MiGetPfnEntry(Pfn); + if (Page->Flags.Type == MM_PHYSICAL_PAGE_USED && + Page->Flags.Consumer == MC_USER) + { + RemoveEntryList(&Page->ListEntry); + InsertTailList(&UserPageListHead, &Page->ListEntry); } KeReleaseSpinLock(&PageListLock, oldIrql); } @@ -112,16 +134,18 @@ PLIST_ENTRY NextListEntry; PHYSICAL_PAGE* PageDescriptor; KIRQL oldIrql; - - KeAcquireSpinLock(&PageListLock, &oldIrql); - if (MmPageArray[PreviousPfn].Flags.Type != MM_PHYSICAL_PAGE_USED || - MmPageArray[PreviousPfn].Flags.Consumer != MC_USER) + PPHYSICAL_PAGE Page; + + KeAcquireSpinLock(&PageListLock, &oldIrql); + Page = MiGetPfnEntry(PreviousPfn); + if (Page->Flags.Type != MM_PHYSICAL_PAGE_USED || + Page->Flags.Consumer != MC_USER) { NextListEntry = UserPageListHead.Flink; } else { - NextListEntry = MmPageArray[PreviousPfn].ListEntry.Flink; + NextListEntry = Page->ListEntry.Flink; } if (NextListEntry == &UserPageListHead) { @@ -166,7 +190,7 @@ */ for (i = j == 0 ? 0x100000 / PAGE_SIZE : LowestAcceptableAddress.LowPart / PAGE_SIZE; i <= last; ) { - if (MmPageArray[i].Flags.Type == MM_PHYSICAL_PAGE_FREE) + if (MiGetPfnEntry(i)->Flags.Type == MM_PHYSICAL_PAGE_FREE) { if (start == (ULONG)-1) { @@ -201,30 +225,32 @@ { for (i = start; i < (start + length); i++) { - RemoveEntryList(&MmPageArray[i].ListEntry); + PPHYSICAL_PAGE Page; + Page = MiGetPfnEntry(i); + RemoveEntryList(&Page->ListEntry); if (MmPageArray[i].Flags.Zero == 0) { UnzeroedPageCount--; } MmStats.NrFreePages--; MmStats.NrSystemPages++; - MmPageArray[i].Flags.Type = MM_PHYSICAL_PAGE_USED; - MmPageArray[i].Flags.Consumer = MC_NPPOOL; - MmPageArray[i].ReferenceCount = 1; - MmPageArray[i].LockCount = 0; - MmPageArray[i].MapCount = 0; - MmPageArray[i].SavedSwapEntry = 0; + Page->Flags.Type = MM_PHYSICAL_PAGE_USED; + Page->Flags.Consumer = MC_NPPOOL; + Page->ReferenceCount = 1; + Page->LockCount = 0; + Page->MapCount = 0; + Page->SavedSwapEntry = 0; } KeReleaseSpinLock(&PageListLock, oldIrql); for (i = start; i < (start + length); i++) { - if (MmPageArray[i].Flags.Zero == 0) + if (MiGetPfnEntry(i)->Flags.Zero == 0) { MiZeroPage(i); } else { - MmPageArray[i].Flags.Zero = 0; + MiGetPfnEntry(i)->Flags.Zero = 0; } } return start; @@ -292,6 +318,7 @@ NTSTATUS Status; PFN_TYPE Pfn = 0; ULONG PdeStart = PsGetCurrentProcess()->Pcb.DirectoryTableBase.LowPart; + PHYSICAL_PAGE UsedPage; ULONG PdePageStart, PdePageEnd; ULONG VideoPageStart, VideoPageEnd; ULONG KernelPageStart, KernelPageEnd; @@ -344,7 +371,14 @@
/* Clear the PFN database */ RtlZeroMemory(MmPageArray, MmPageArraySize * sizeof(PHYSICAL_PAGE)); - + + /* This is what a used page looks like */ + RtlZeroMemory(&UsedPage, sizeof(UsedPage)); + UsedPage.Flags.Type = MM_PHYSICAL_PAGE_USED; + UsedPage.Flags.Consumer = MC_NPPOOL; + UsedPage.ReferenceCount = 2; + UsedPage.MapCount = 1; + /* We'll be applying a bunch of hacks -- precompute some static values */ PdePageStart = PdeStart / PAGE_SIZE; PdePageEnd = MmFreeLdrPageDirectoryEnd / PAGE_SIZE; @@ -363,37 +397,25 @@ if (i == 0) { /* Page 0 is reserved for the IVT */ - MmPageArray[i].Flags.Type = MM_PHYSICAL_PAGE_USED; - MmPageArray[i].Flags.Consumer = MC_NPPOOL; - MmPageArray[i].ReferenceCount = 2; - MmPageArray[i].MapCount = 1; + MmPageArray[i] = UsedPage; MmStats.NrReservedPages++; } else if (i == 1) { /* Page 1 is reserved for the PCR */ - MmPageArray[i].Flags.Type = MM_PHYSICAL_PAGE_USED; - MmPageArray[i].Flags.Consumer = MC_NPPOOL; - MmPageArray[i].ReferenceCount = 2; - MmPageArray[i].MapCount = 1; + MmPageArray[i] = UsedPage; MmStats.NrReservedPages++; } else if (i == 2) { /* Page 2 is reserved for the KUSER_SHARED_DATA */ - MmPageArray[i].Flags.Type = MM_PHYSICAL_PAGE_USED; - MmPageArray[i].Flags.Consumer = MC_NPPOOL; - MmPageArray[i].ReferenceCount = 2; - MmPageArray[i].MapCount = 1; + MmPageArray[i] = UsedPage; MmStats.NrReservedPages++; } else if ((i >= PdePageStart) && (i < PdePageEnd)) { /* These pages contain the initial FreeLDR PDEs */ - MmPageArray[i].Flags.Type = MM_PHYSICAL_PAGE_USED; - MmPageArray[i].Flags.Consumer = MC_NPPOOL; - MmPageArray[i].ReferenceCount = 2; - MmPageArray[i].MapCount = 1; + MmPageArray[i] = UsedPage; MmStats.NrReservedPages++; } else if ((i >= VideoPageStart) && (i < VideoPageEnd)) @@ -411,19 +433,13 @@ else if ((i >= KernelPageStart) && (i < KernelPageEnd)) { /* These are pages beloning to the kernel */ - MmPageArray[i].Flags.Type = MM_PHYSICAL_PAGE_USED; - MmPageArray[i].Flags.Consumer = MC_NPPOOL; - MmPageArray[i].ReferenceCount = 2; - MmPageArray[i].MapCount = 1; + MmPageArray[i] = UsedPage; MmStats.NrSystemPages++; } else if (i >= (MiFreeDescriptor->BasePage + MiFreeDescriptor->PageCount)) { /* These are pages we allocated above to hold the PFN DB */ - MmPageArray[i].Flags.Type = MM_PHYSICAL_PAGE_USED; - MmPageArray[i].Flags.Consumer = MC_NPPOOL; - MmPageArray[i].ReferenceCount = 2; - MmPageArray[i].MapCount = 1; + MmPageArray[i] = UsedPage; MmStats.NrSystemPages++; } else @@ -463,9 +479,8 @@ { KIRQL oldIrql;
- ASSERT(Pfn < MmPageArraySize); - KeAcquireSpinLock(&PageListLock, &oldIrql); - MmPageArray[Pfn].AllFlags = Flags; + KeAcquireSpinLock(&PageListLock, &oldIrql); + MiGetPfnEntry(Pfn)->AllFlags = Flags; KeReleaseSpinLock(&PageListLock, oldIrql); }
@@ -473,14 +488,25 @@ NTAPI MmSetRmapListHeadPage(PFN_TYPE Pfn, struct _MM_RMAP_ENTRY* ListHead) { - MmPageArray[Pfn].RmapListHead = ListHead; + KIRQL oldIrql; + + KeAcquireSpinLock(&PageListLock, &oldIrql); + MiGetPfnEntry(Pfn)->RmapListHead = ListHead; + KeReleaseSpinLock(&PageListLock, oldIrql); }
struct _MM_RMAP_ENTRY* NTAPI MmGetRmapListHeadPage(PFN_TYPE Pfn) { - return(MmPageArray[Pfn].RmapListHead); + KIRQL oldIrql; + struct _MM_RMAP_ENTRY* ListHead; + + KeAcquireSpinLock(&PageListLock, &oldIrql); + ListHead = MiGetPfnEntry(Pfn)->RmapListHead; + KeReleaseSpinLock(&PageListLock, oldIrql); + + return(ListHead); }
VOID @@ -488,17 +514,19 @@ MmMarkPageMapped(PFN_TYPE Pfn) { KIRQL oldIrql; + PPHYSICAL_PAGE Page;
if (Pfn < MmPageArraySize) { KeAcquireSpinLock(&PageListLock, &oldIrql); - if (MmPageArray[Pfn].Flags.Type == MM_PHYSICAL_PAGE_FREE) + Page = MiGetPfnEntry(Pfn); + if (Page->Flags.Type == MM_PHYSICAL_PAGE_FREE) { DPRINT1("Mapping non-used page\n"); KEBUGCHECK(0); } - MmPageArray[Pfn].MapCount++; - MmPageArray[Pfn].ReferenceCount++; + Page->MapCount++; + Page->ReferenceCount++; KeReleaseSpinLock(&PageListLock, oldIrql); } } @@ -508,22 +536,24 @@ MmMarkPageUnmapped(PFN_TYPE Pfn) { KIRQL oldIrql; + PPHYSICAL_PAGE Page;
if (Pfn < MmPageArraySize) { KeAcquireSpinLock(&PageListLock, &oldIrql); - if (MmPageArray[Pfn].Flags.Type == MM_PHYSICAL_PAGE_FREE) + Page = MiGetPfnEntry(Pfn); + if (Page->Flags.Type == MM_PHYSICAL_PAGE_FREE) { DPRINT1("Unmapping non-used page\n"); KEBUGCHECK(0); } - if (MmPageArray[Pfn].MapCount == 0) + if (Page->MapCount == 0) { DPRINT1("Unmapping not mapped page\n"); KEBUGCHECK(0); } - MmPageArray[Pfn].MapCount--; - MmPageArray[Pfn].ReferenceCount--; + Page->MapCount--; + Page->ReferenceCount--; KeReleaseSpinLock(&PageListLock, oldIrql); } } @@ -535,9 +565,8 @@ KIRQL oldIrql; ULONG Flags;
- ASSERT(Pfn < MmPageArraySize); - KeAcquireSpinLock(&PageListLock, &oldIrql); - Flags = MmPageArray[Pfn].AllFlags; + KeAcquireSpinLock(&PageListLock, &oldIrql); + Flags = MiGetPfnEntry(Pfn)->AllFlags; KeReleaseSpinLock(&PageListLock, oldIrql);
return(Flags); @@ -550,9 +579,8 @@ { KIRQL oldIrql;
- ASSERT(Pfn < MmPageArraySize); - KeAcquireSpinLock(&PageListLock, &oldIrql); - MmPageArray[Pfn].SavedSwapEntry = SavedSwapEntry; + KeAcquireSpinLock(&PageListLock, &oldIrql); + MiGetPfnEntry(Pfn)->SavedSwapEntry = SavedSwapEntry; KeReleaseSpinLock(&PageListLock, oldIrql); }
@@ -563,9 +591,8 @@ SWAPENTRY SavedSwapEntry; KIRQL oldIrql;
- ASSERT(Pfn < MmPageArraySize); - KeAcquireSpinLock(&PageListLock, &oldIrql); - SavedSwapEntry = MmPageArray[Pfn].SavedSwapEntry; + KeAcquireSpinLock(&PageListLock, &oldIrql); + SavedSwapEntry = MiGetPfnEntry(Pfn)->SavedSwapEntry; KeReleaseSpinLock(&PageListLock, oldIrql);
return(SavedSwapEntry); @@ -576,6 +603,7 @@ MmReferencePageUnsafe(PFN_TYPE Pfn) { KIRQL oldIrql; + PPHYSICAL_PAGE Page;
DPRINT("MmReferencePageUnsafe(PysicalAddress %x)\n", Pfn << PAGE_SHIFT);
@@ -586,13 +614,14 @@
KeAcquireSpinLock(&PageListLock, &oldIrql);
- if (MmPageArray[Pfn].Flags.Type != MM_PHYSICAL_PAGE_USED) + Page = MiGetPfnEntry(Pfn); + if (Page->Flags.Type != MM_PHYSICAL_PAGE_USED) { DPRINT1("Referencing non-used page\n"); KEBUGCHECK(0); }
- MmPageArray[Pfn].ReferenceCount++; + Page->ReferenceCount++; KeReleaseSpinLock(&PageListLock, oldIrql); }
@@ -616,6 +645,7 @@ { KIRQL oldIrql; ULONG RCount; + PPHYSICAL_PAGE Page;
DPRINT("MmGetReferenceCountPage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
@@ -625,14 +655,14 @@ }
KeAcquireSpinLock(&PageListLock, &oldIrql); - - if (MmPageArray[Pfn].Flags.Type != MM_PHYSICAL_PAGE_USED) + Page = MiGetPfnEntry(Pfn); + if (Page->Flags.Type != MM_PHYSICAL_PAGE_USED) { DPRINT1("Getting reference count for free page\n"); KEBUGCHECK(0); }
- RCount = MmPageArray[Pfn].ReferenceCount; + RCount = Page->ReferenceCount;
KeReleaseSpinLock(&PageListLock, oldIrql); return(RCount); @@ -645,77 +675,70 @@
DPRINT("MmIsPageInUse(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
- if (Pfn == 0 || Pfn >= MmPageArraySize) - { - KEBUGCHECK(0); - } + return (MiGetPfnEntry(Pfn)->Flags.Type == MM_PHYSICAL_PAGE_USED); +} + +VOID +NTAPI +MmDereferencePage(PFN_TYPE Pfn) +{ + KIRQL oldIrql; + PPHYSICAL_PAGE Page; + + DPRINT("MmDereferencePage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT); + + KeAcquireSpinLock(&PageListLock, &oldIrql);
- return (MmPageArray[Pfn].Flags.Type == MM_PHYSICAL_PAGE_USED); -} - -VOID -NTAPI -MmDereferencePage(PFN_TYPE Pfn) -{ - KIRQL oldIrql; - - DPRINT("MmDereferencePage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT); - - if (Pfn == 0 || Pfn >= MmPageArraySize) - { - KEBUGCHECK(0); - } - - KeAcquireSpinLock(&PageListLock, &oldIrql); - - if (MmPageArray[Pfn].Flags.Type != MM_PHYSICAL_PAGE_USED) + Page = MiGetPfnEntry(Pfn); + + if (Page->Flags.Type != MM_PHYSICAL_PAGE_USED) { DPRINT1("Dereferencing free page\n"); KEBUGCHECK(0); } - if (MmPageArray[Pfn].ReferenceCount == 0) + if (Page->ReferenceCount == 0) { DPRINT1("Derefrencing page with reference count 0\n"); KEBUGCHECK(0); }
- MmPageArray[Pfn].ReferenceCount--; - if (MmPageArray[Pfn].ReferenceCount == 0) + Page->ReferenceCount--; + if (Page->ReferenceCount == 0) { MmStats.NrFreePages++; MmStats.NrSystemPages--; - if (MmPageArray[Pfn].Flags.Consumer == MC_USER) RemoveEntryList(&MmPageArray[Pfn].ListEntry); - if (MmPageArray[Pfn].RmapListHead != NULL) + if (Page->Flags.Consumer == MC_USER) RemoveEntryList(&Page->ListEntry); + if (Page->RmapListHead != NULL) { DPRINT1("Freeing page with rmap entries.\n"); KEBUGCHECK(0); } - if (MmPageArray[Pfn].MapCount != 0) + if (Page->MapCount != 0) { DPRINT1("Freeing mapped page (0x%x count %d)\n", - Pfn << PAGE_SHIFT, MmPageArray[Pfn].MapCount); + Pfn << PAGE_SHIFT, Page->MapCount); KEBUGCHECK(0); } - if (MmPageArray[Pfn].LockCount > 0) + if (Page->LockCount > 0) { DPRINT1("Freeing locked page\n"); KEBUGCHECK(0); } - if (MmPageArray[Pfn].SavedSwapEntry != 0) + if (Page->SavedSwapEntry != 0) { DPRINT1("Freeing page with swap entry.\n"); KEBUGCHECK(0); } - if (MmPageArray[Pfn].Flags.Type != MM_PHYSICAL_PAGE_USED) + if (Page->Flags.Type != MM_PHYSICAL_PAGE_USED) { DPRINT1("Freeing page with flags %x\n", - MmPageArray[Pfn].Flags.Type); + Page->Flags.Type); KEBUGCHECK(0); } - MmPageArray[Pfn].Flags.Type = MM_PHYSICAL_PAGE_FREE; - MmPageArray[Pfn].Flags.Consumer = MC_MAXIMUM; + Page->Flags.Type = MM_PHYSICAL_PAGE_FREE; + Page->Flags.Consumer = MC_MAXIMUM; InsertTailList(&FreeUnzeroedPageListHead, - &MmPageArray[Pfn].ListEntry); + &Page->ListEntry); UnzeroedPageCount++; if (UnzeroedPageCount > 8 && 0 == KeReadStateEvent(&ZeroPageThreadEvent)) { @@ -731,23 +754,20 @@ { KIRQL oldIrql; ULONG LockCount; + PPHYSICAL_PAGE Page;
DPRINT("MmGetLockCountPage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
- if (Pfn == 0 || Pfn >= MmPageArraySize) - { - KEBUGCHECK(0); - } - - KeAcquireSpinLock(&PageListLock, &oldIrql); - - if (MmPageArray[Pfn].Flags.Type != MM_PHYSICAL_PAGE_USED) + KeAcquireSpinLock(&PageListLock, &oldIrql); + + Page = MiGetPfnEntry(Pfn); + if (Page->Flags.Type != MM_PHYSICAL_PAGE_USED) { DPRINT1("Getting lock count for free page\n"); KEBUGCHECK(0); }
- LockCount = MmPageArray[Pfn].LockCount; + LockCount = Page->LockCount; KeReleaseSpinLock(&PageListLock, oldIrql);
return(LockCount); @@ -758,23 +778,20 @@ MmLockPageUnsafe(PFN_TYPE Pfn) { KIRQL oldIrql; + PPHYSICAL_PAGE Page;
DPRINT("MmLockPageUnsafe(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
- if (Pfn == 0 || Pfn >= MmPageArraySize) - { - return; - } - - KeAcquireSpinLock(&PageListLock, &oldIrql); - - if (MmPageArray[Pfn].Flags.Type != MM_PHYSICAL_PAGE_USED) + KeAcquireSpinLock(&PageListLock, &oldIrql); + + Page = MiGetPfnEntry(Pfn); + if (Page->Flags.Type != MM_PHYSICAL_PAGE_USED) { DPRINT1("Locking free page\n"); KEBUGCHECK(0); }
- MmPageArray[Pfn].LockCount++; + Page->LockCount++; KeReleaseSpinLock(&PageListLock, oldIrql); }
@@ -784,11 +801,6 @@ { DPRINT("MmLockPage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
- if (Pfn == 0 || Pfn >= MmPageArraySize) - { - KEBUGCHECK(0); - } - MmLockPageUnsafe(Pfn); }
@@ -797,23 +809,20 @@ MmUnlockPage(PFN_TYPE Pfn) { KIRQL oldIrql; + PPHYSICAL_PAGE Page;
DPRINT("MmUnlockPage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
- if (Pfn == 0 || Pfn >= MmPageArraySize) - { - KEBUGCHECK(0); - } - - KeAcquireSpinLock(&PageListLock, &oldIrql); - - if (MmPageArray[Pfn].Flags.Type != MM_PHYSICAL_PAGE_USED) + KeAcquireSpinLock(&PageListLock, &oldIrql); + + Page = MiGetPfnEntry(Pfn); + if (Page->Flags.Type != MM_PHYSICAL_PAGE_USED) { DPRINT1("Unlocking free page\n"); KEBUGCHECK(0); }
- MmPageArray[Pfn].LockCount--; + Page->LockCount--; KeReleaseSpinLock(&PageListLock, oldIrql); }
@@ -1029,13 +1038,13 @@ for (i = 0; i < NumberOfPagesFound; i++) { pfn = Pages[i]; - if (MmPageArray[pfn].Flags.Zero == 0) + if (MiGetPfnEntry(pfn)->Flags.Zero == 0) { MiZeroPage(pfn); } else { - MmPageArray[pfn].Flags.Zero = 0; + MiGetPfnEntry(pfn)->Flags.Zero = 0; } }