mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
[NTOS:Mm] Handle failure to allocate pages in the page fault handler
This commit is contained in:
parent
3ae12d5a8c
commit
7c6e4d38c7
2 changed files with 95 additions and 27 deletions
|
@ -653,7 +653,7 @@ MiResolveDemandZeroFault(IN PVOID Address,
|
|||
ASSERT(PointerPte->u.Hard.Valid == 0);
|
||||
|
||||
/* Assert we have enough pages */
|
||||
ASSERT(MmAvailablePages >= 32);
|
||||
//ASSERT(MmAvailablePages >= 32);
|
||||
|
||||
#if MI_TRACE_PFNS
|
||||
if (UserPdeFault) MI_SET_USAGE(MI_USAGE_PAGE_TABLE);
|
||||
|
@ -698,6 +698,12 @@ MiResolveDemandZeroFault(IN PVOID Address,
|
|||
}
|
||||
}
|
||||
|
||||
if (PageFrameNumber == 0)
|
||||
{
|
||||
MiReleasePfnLock(OldIrql);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* Initialize it */
|
||||
MiInitializePfn(PageFrameNumber, PointerPte, TRUE);
|
||||
|
||||
|
@ -920,6 +926,10 @@ MiResolvePageFileFault(_In_ BOOLEAN StoreInstruction,
|
|||
/* Get any page, it will be overwritten */
|
||||
Color = MI_GET_NEXT_PROCESS_COLOR(CurrentProcess);
|
||||
Page = MiRemoveAnyPage(Color);
|
||||
if (Page == 0)
|
||||
{
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* Initialize this PFN */
|
||||
MiInitializePfn(Page, PointerPte, StoreInstruction);
|
||||
|
@ -1230,6 +1240,11 @@ MiResolveProtoPteFault(IN BOOLEAN StoreInstruction,
|
|||
Color = MI_GET_NEXT_COLOR();
|
||||
|
||||
PageFrameIndex = MiRemoveAnyPage(Color);
|
||||
if (PageFrameIndex == 0)
|
||||
{
|
||||
MiReleasePfnLock(OldIrql);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* Perform the copy */
|
||||
MiCopyPfn(PageFrameIndex, ProtoPageFrameIndex);
|
||||
|
@ -1669,9 +1684,9 @@ MiDispatchFault(IN ULONG FaultCode,
|
|||
}
|
||||
|
||||
//
|
||||
// Generate an access fault
|
||||
// Return status
|
||||
//
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
|
@ -2126,11 +2141,15 @@ UserFault:
|
|||
}
|
||||
|
||||
/* Resolve a demand zero fault */
|
||||
MiResolveDemandZeroFault(PointerPpe,
|
||||
Status = MiResolveDemandZeroFault(PointerPpe,
|
||||
PointerPxe,
|
||||
MM_EXECUTE_READWRITE,
|
||||
CurrentProcess,
|
||||
MM_NOIRQL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
goto ExitUser;
|
||||
}
|
||||
|
||||
/* We should come back with a valid PXE */
|
||||
ASSERT(PointerPxe->u.Hard.Valid == 1);
|
||||
|
@ -2160,11 +2179,15 @@ UserFault:
|
|||
}
|
||||
|
||||
/* Resolve a demand zero fault */
|
||||
MiResolveDemandZeroFault(PointerPde,
|
||||
Status = MiResolveDemandZeroFault(PointerPde,
|
||||
PointerPpe,
|
||||
MM_EXECUTE_READWRITE,
|
||||
CurrentProcess,
|
||||
MM_NOIRQL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
goto ExitUser;
|
||||
}
|
||||
|
||||
/* We should come back with a valid PPE */
|
||||
ASSERT(PointerPpe->u.Hard.Valid == 1);
|
||||
|
@ -2203,11 +2226,16 @@ UserFault:
|
|||
}
|
||||
|
||||
/* Resolve a demand zero fault */
|
||||
MiResolveDemandZeroFault(PointerPte,
|
||||
Status = MiResolveDemandZeroFault(PointerPte,
|
||||
PointerPde,
|
||||
MM_EXECUTE_READWRITE,
|
||||
CurrentProcess,
|
||||
MM_NOIRQL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
goto ExitUser;
|
||||
}
|
||||
|
||||
#if _MI_PAGING_LEVELS >= 3
|
||||
MiIncrementPageTableReferences(PointerPte);
|
||||
#endif
|
||||
|
@ -2254,6 +2282,12 @@ UserFault:
|
|||
|
||||
/* Allocate a new page and copy it */
|
||||
PageFrameIndex = MiRemoveAnyPage(MI_GET_NEXT_PROCESS_COLOR(CurrentProcess));
|
||||
if (PageFrameIndex == 0)
|
||||
{
|
||||
MiReleasePfnLock(LockIrql);
|
||||
Status = STATUS_NO_MEMORY;
|
||||
goto ExitUser;
|
||||
}
|
||||
OldPageFrameIndex = PFN_FROM_PTE(&TempPte);
|
||||
|
||||
MiCopyPfn(PageFrameIndex, OldPageFrameIndex);
|
||||
|
@ -2308,11 +2342,15 @@ UserFault:
|
|||
(TempPte.u.Long == (MM_EXECUTE_READWRITE << MM_PTE_SOFTWARE_PROTECTION_BITS)))
|
||||
{
|
||||
/* Resolve the fault */
|
||||
MiResolveDemandZeroFault(Address,
|
||||
Status = MiResolveDemandZeroFault(Address,
|
||||
PointerPte,
|
||||
TempPte.u.Soft.Protection,
|
||||
CurrentProcess,
|
||||
MM_NOIRQL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
goto ExitUser;
|
||||
}
|
||||
|
||||
#if MI_TRACE_PFNS
|
||||
/* Update debug info */
|
||||
|
@ -2410,7 +2448,7 @@ UserFault:
|
|||
OldIrql = MiAcquirePfnLock();
|
||||
|
||||
/* Make sure we have enough pages */
|
||||
ASSERT(MmAvailablePages >= 32);
|
||||
//ASSERT(MmAvailablePages >= 32);
|
||||
|
||||
/* Try to get a zero page */
|
||||
MI_SET_USAGE(MI_USAGE_PEB_TEB);
|
||||
|
@ -2421,11 +2459,16 @@ UserFault:
|
|||
{
|
||||
/* Grab a page out of there. Later we should grab a colored zero page */
|
||||
PageFrameIndex = MiRemoveAnyPage(Color);
|
||||
ASSERT(PageFrameIndex);
|
||||
|
||||
/* Release the lock since we need to do some zeroing */
|
||||
MiReleasePfnLock(OldIrql);
|
||||
|
||||
if (PageFrameIndex == 0)
|
||||
{
|
||||
Status = STATUS_NO_MEMORY;
|
||||
goto ExitUser;
|
||||
}
|
||||
|
||||
/* Zero out the page, since it's for user-mode */
|
||||
MiZeroPfn(PageFrameIndex);
|
||||
|
||||
|
@ -2568,6 +2611,8 @@ UserFault:
|
|||
TrapInformation,
|
||||
Vad);
|
||||
|
||||
ExitUser:
|
||||
|
||||
/* Return the status */
|
||||
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
||||
MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
|
||||
|
|
|
@ -1335,9 +1335,16 @@ MmMakeSegmentResident(
|
|||
RtlZeroMemory(Pages, BYTES_TO_PAGES(ReadLength) * sizeof(PFN_NUMBER));
|
||||
for (UINT i = 0; i < BYTES_TO_PAGES(ReadLength); i++)
|
||||
{
|
||||
/* MmRequestPageMemoryConsumer succeeds or bugchecks */
|
||||
(void)MmRequestPageMemoryConsumer(MC_USER, FALSE, &Pages[i]);
|
||||
Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Pages[i]);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Damn. Roll-back. */
|
||||
for (UINT j = 0; j < i; j++)
|
||||
MmReleasePageMemoryConsumer(MC_USER, Pages[j]);
|
||||
goto Failed;
|
||||
}
|
||||
}
|
||||
|
||||
Mdl->MdlFlags |= MDL_PAGES_LOCKED | MDL_IO_PAGE_READ;
|
||||
|
||||
LARGE_INTEGER FileOffset;
|
||||
|
@ -1389,6 +1396,7 @@ MmMakeSegmentResident(
|
|||
for (UINT i = 0; i < BYTES_TO_PAGES(ReadLength); i++)
|
||||
MmReleasePageMemoryConsumer(MC_USER, Pages[i]);
|
||||
|
||||
Failed:
|
||||
MmLockSectionSegment(Segment);
|
||||
while (ChunkOffset < ChunkEnd)
|
||||
{
|
||||
|
@ -1613,6 +1621,15 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
|||
return STATUS_MM_RESTART_OPERATION;
|
||||
}
|
||||
|
||||
MI_SET_USAGE(MI_USAGE_SECTION);
|
||||
if (Process) MI_SET_PROCESS2(Process->ImageFileName);
|
||||
if (!Process) MI_SET_PROCESS2("Kernel Section");
|
||||
Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Must be private page we have swapped out.
|
||||
*/
|
||||
|
@ -1627,14 +1644,6 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
|||
MmCreatePageFileMapping(Process, Address, MM_WAIT_ENTRY);
|
||||
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
MI_SET_USAGE(MI_USAGE_SECTION);
|
||||
if (Process) MI_SET_PROCESS2(Process->ImageFileName);
|
||||
if (!Process) MI_SET_PROCESS2("Kernel Section");
|
||||
Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
KeBugCheck(MEMORY_MANAGEMENT);
|
||||
}
|
||||
|
||||
Status = MmReadFromSwapPage(SwapEntry, Page);
|
||||
if (!NT_SUCCESS(Status))
|
||||
|
@ -1736,7 +1745,12 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
|||
MI_SET_USAGE(MI_USAGE_SECTION);
|
||||
if (Process) MI_SET_PROCESS2(Process->ImageFileName);
|
||||
if (!Process) MI_SET_PROCESS2("Kernel Section");
|
||||
MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page);
|
||||
Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
MmUnlockSectionSegment(Segment);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
MmSetPageEntrySectionSegment(Segment, &Offset, MAKE_SSE(Page << PAGE_SHIFT, 1));
|
||||
MmUnlockSectionSegment(Segment);
|
||||
|
||||
|
@ -1770,6 +1784,10 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
|||
MmLockAddressSpace(AddressSpace);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
if (Status == STATUS_NO_MEMORY)
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
/* Damn */
|
||||
DPRINT1("Failed to page data in!\n");
|
||||
return STATUS_IN_PAGE_ERROR;
|
||||
|
@ -1794,6 +1812,13 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
|||
return STATUS_MM_RESTART_OPERATION;
|
||||
}
|
||||
|
||||
Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
MmUnlockSectionSegment(Segment);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Release all our locks and read in the page from disk
|
||||
*/
|
||||
|
@ -1801,11 +1826,6 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
|||
MmUnlockSectionSegment(Segment);
|
||||
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
KeBugCheck(MEMORY_MANAGEMENT);
|
||||
}
|
||||
|
||||
Status = MmReadFromSwapPage(SwapEntry, Page);
|
||||
if (!NT_SUCCESS(Status))
|
||||
|
@ -1905,6 +1925,7 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
|
|||
BOOLEAN Cow = FALSE;
|
||||
ULONG NewProtect;
|
||||
BOOLEAN Unmapped;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("MmAccessFaultSectionView(%p, %p, %p)\n", AddressSpace, MemoryArea, Address);
|
||||
|
||||
|
@ -1990,9 +2011,11 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
|
|||
/*
|
||||
* Allocate a page
|
||||
*/
|
||||
if (!NT_SUCCESS(MmRequestPageMemoryConsumer(MC_USER, TRUE, &NewPage)))
|
||||
Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &NewPage);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
KeBugCheck(MEMORY_MANAGEMENT);
|
||||
MmUnlockSectionSegment(Segment);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue