return MmSharedUserDataPte;
}
- /* Find the VAD, it must exist, since we only handle PEB/TEB */
+ /* Find the VAD, it might not exist if the address is bogus */
Vad = MiLocateAddress(VirtualAddress);
- ASSERT(Vad);
+ if (!Vad)
+ {
+ /* Bogus virtual address */
+ *ProtectCode = MM_NOACCESS;
+ return NULL;
+ }
/* This must be a TEB/PEB VAD */
ASSERT(Vad->u.VadFlags.PrivateMemory == TRUE);
#ifdef _M_AMD64
ASSERT(FALSE);
#else
- /* This seems to be making the assumption that one PDE is one page long */
- C_ASSERT(PAGE_SIZE == (PD_COUNT * (sizeof(MMPTE) * PDE_COUNT)));
-
//
// Copy it from our double-mapped system page directory
//
InterlockedExchangePte(PointerPde,
- MmSystemPagePtes[((ULONG_PTR)PointerPde &
- (PAGE_SIZE - 1)) /
- sizeof(MMPTE)].u.Long);
+ MmSystemPagePtes[((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE)].u.Long);
#endif
}
IN PEPROCESS Process,
IN KIRQL OldIrql)
{
- PFN_NUMBER PageFrameNumber;
+ PFN_NUMBER PageFrameNumber = 0;
MMPTE TempPte;
BOOLEAN NeedZero = FALSE;
+ ULONG Color;
DPRINT("ARM3 Demand Zero Page Fault Handler for address: %p in process: %p\n",
Address,
Process);
/* No forking yet */
ASSERT(Process->ForkInProgress == NULL);
+ /* Get process color */
+ Color = MI_GET_NEXT_PROCESS_COLOR(Process);
+
/* We'll need a zero page */
NeedZero = TRUE;
}
+ else
+ {
+ /* Get the next system page color */
+ Color = MI_GET_NEXT_COLOR();
+ }
//
// Lock the PFN database
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
ASSERT(PointerPte->u.Hard.Valid == 0);
- /* Get a page */
- PageFrameNumber = MiRemoveAnyPage(0);
- DPRINT("New pool page: %lx\n", PageFrameNumber);
+ /* Do we need a zero page? */
+ if (NeedZero)
+ {
+ /* Try to get one, if we couldn't grab a free page and zero it */
+ PageFrameNumber = MiRemoveZeroPageSafe(Color);
+ if (PageFrameNumber) NeedZero = FALSE;
+ }
+
+ /* Did we get a page? */
+ if (!PageFrameNumber)
+ {
+ /* We either failed to find a zero page, or this is a system request */
+ PageFrameNumber = MiRemoveAnyPage(Color);
+ DPRINT("New pool page: %lx\n", PageFrameNumber);
+ }
/* Initialize it */
MiInitializePfn(PageFrameNumber, PointerPte, TRUE);
ULONG ProtectionCode;
PMMVAD Vad;
PFN_NUMBER PageFrameIndex;
+ ULONG Color;
DPRINT("ARM3 FAULT AT: %p\n", Address);
//
return STATUS_SUCCESS;
}
- //
- // We don't implement prototype PTEs
- //
- ASSERT(TempPte.u.Soft.Prototype == 0);
+ /* Check one kind of prototype PTE */
+ if (TempPte.u.Soft.Prototype)
+ {
+ /* The one used for protected pool... */
+ ASSERT(MmProtectFreedNonPagedPool == TRUE);
+
+ /* Make sure protected pool is on, and that this is a pool address */
+ if ((MmProtectFreedNonPagedPool) &&
+ (((Address >= MmNonPagedPoolStart) &&
+ (Address < (PVOID)((ULONG_PTR)MmNonPagedPoolStart +
+ MmSizeOfNonPagedPoolInBytes))) ||
+ ((Address >= MmNonPagedPoolExpansionStart) &&
+ (Address < MmNonPagedPoolEnd))))
+ {
+ /* Bad boy, bad boy, whatcha gonna do, whatcha gonna do when ARM3 comes for you! */
+ KeBugCheckEx(DRIVER_CAUGHT_MODIFYING_FREED_POOL,
+ (ULONG_PTR)Address,
+ StoreInstruction,
+ Mode,
+ 4);
+ }
+ }
//
// We don't implement transition PTEs
/* Check if this address range belongs to a valid allocation (VAD) */
ProtoPte = MiCheckVirtualAddress(Address, &ProtectionCode, &Vad);
- ASSERT(ProtectionCode != MM_NOACCESS);
-
+ if (ProtectionCode == MM_NOACCESS)
+ {
+ /* This is a bogus VA */
+ Status = STATUS_ACCESS_VIOLATION;
+
+ /* Could be a not-yet-mapped paged pool page table */
+#if (_MI_PAGING_LEVELS == 2)
+ MiCheckPdeForPagedPool(Address);
+#endif
+ /* See if that fixed it */
+ if (PointerPte->u.Hard.Valid == 1) Status = STATUS_SUCCESS;
+
+ /* Return the status */
+ MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
+ return Status;
+ }
+
/* Did we get a prototype PTE back? */
if (!ProtoPte)
{
/* Lock the PFN database since we're going to grab a page */
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+ /* Try to get a zero page */
+ Color = MI_GET_NEXT_PROCESS_COLOR(CurrentProcess);
+ PageFrameIndex = MiRemoveZeroPageSafe(Color);
+ if (!PageFrameIndex)
+ {
+ /* Grab a page out of there. Later we should grab a colored zero page */
+ PageFrameIndex = MiRemoveAnyPage(Color);
+ ASSERT(PageFrameIndex);
- /* Grab a page out of there. Later we should grab a colored zero page */
- PageFrameIndex = MiRemoveAnyPage(0);
- ASSERT(PageFrameIndex);
-
- /* Release the lock since we need to do some zeroing */
- KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+ /* Release the lock since we need to do some zeroing */
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
- /* Zero out the page, since it's for user-mode */
- MiZeroPfn(PageFrameIndex);
+ /* Zero out the page, since it's for user-mode */
+ MiZeroPfn(PageFrameIndex);
- /* Grab the lock again so we can initialize the PFN entry */
- OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+ /* Grab the lock again so we can initialize the PFN entry */
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+ }
/* Initialize the PFN entry now */
MiInitializePfn(PageFrameIndex, PointerPte, 1);