[NTOSKRNL]

- Allow placement of a wait entry in virgin address space prior to mapping a page.
- Add a wait entry in the address space when paging in section view.
- Correct a problem that previously prevented us from evicting or querying pages that
  had been protected into PAGE_NOACCESS protection by adding a query for disabled
  mappings and handling disabled mappings in a few places (this may be controversial).

svn path=/trunk/; revision=56682
This commit is contained in:
Art Yerkes 2012-06-01 09:01:41 +00:00
parent 15425106b9
commit 2bbb9b2930
4 changed files with 44 additions and 6 deletions

View file

@ -4,7 +4,6 @@
/* TYPES *********************************************************************/
#define MM_WAIT_ENTRY 0x7ffffc00
#define PFN_FROM_SSE(E) ((PFN_NUMBER)((E) >> PAGE_SHIFT))
#define IS_SWAP_FROM_SSE(E) ((E) & 0x00000001)
#define MM_IS_WAIT_PTE(E) \

View file

@ -179,6 +179,10 @@ typedef ULONG_PTR SWAPENTRY;
(PAGE_WRITECOPY | \
PAGE_EXECUTE_WRITECOPY)
//
// Wait entry for marking pages that are being serviced
//
#define MM_WAIT_ENTRY 0x7ffffc00
#define InterlockedCompareExchangePte(PointerPte, Exchange, Comperand) \
InterlockedCompareExchange((PLONG)(PointerPte), Exchange, Comperand)
@ -1263,6 +1267,13 @@ MmIsPagePresent(
PVOID Address
);
BOOLEAN
NTAPI
MmIsDisabledPage(
struct _EPROCESS* Process,
PVOID Address
);
VOID
NTAPI
MmInitGlobalKernelPageDirectory(VOID);

View file

@ -467,7 +467,9 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOLEAN FreePage,
*/
Pte = InterlockedExchangePte(Pt, 0);
WasValid = (Pte & PA_PRESENT);
/* We count a mapping as valid if it's a present page, or it's a nonzero pfn with
* the swap bit unset, indicating a valid page protected to PAGE_NOACCESS. */
WasValid = (Pte & PA_PRESENT) || ((Pte >> PAGE_SHIFT) && !(Pte & 0x800));
if (WasValid)
{
/* Flush the TLB since we transitioned this PTE
@ -700,6 +702,14 @@ MmIsPagePresent(PEPROCESS Process, PVOID Address)
return MmGetPageEntryForProcess(Process, Address) & PA_PRESENT;
}
BOOLEAN
NTAPI
MmIsDisabledPage(PEPROCESS Process, PVOID Address)
{
ULONG_PTR Entry = MmGetPageEntryForProcess(Process, Address);
return !(Entry & PA_PRESENT) && !(Entry & 0x800) && (Entry >> PAGE_SHIFT);
}
BOOLEAN
NTAPI
MmIsPageSwapEntry(PEPROCESS Process, PVOID Address)
@ -738,12 +748,17 @@ MmCreatePageFileMapping(PEPROCESS Process,
if (Pt == NULL)
{
/* Nobody should page out an address that hasn't even been mapped */
KeBugCheck(MEMORY_MANAGEMENT);
/* But we might place a wait entry first, requiring the page table */
if (SwapEntry != MM_WAIT_ENTRY)
{
KeBugCheck(MEMORY_MANAGEMENT);
}
Pt = MmGetPageTableForProcess(Process, Address, TRUE);
}
Pte = InterlockedExchangePte(Pt, SwapEntry << 1);
if (Pte != 0)
{
KeBugCheck(MEMORY_MANAGEMENT);
KeBugCheckEx(MEMORY_MANAGEMENT, SwapEntry, (ULONG_PTR)Process, (ULONG_PTR)Address, 0);
}
if (Address < MmSystemRangeStart)
@ -975,7 +990,8 @@ MmSetPageProtect(PEPROCESS Process, PVOID Address, ULONG flProtect)
}
Pte = InterlockedExchangePte(Pt, PAGE_MASK(*Pt) | Attributes | (*Pt & (PA_ACCESSED|PA_DIRTY)));
if (!(Pte & PA_PRESENT))
// We should be able to bring a page back from PAGE_NOACCESS
if ((Pte & 0x800) || !(Pte >> PAGE_SHIFT))
{
DPRINT1("Invalid Pte %lx\n", Pte);
KeBugCheck(MEMORY_MANAGEMENT);

View file

@ -1223,6 +1223,11 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
return(STATUS_SUCCESS);
}
if (MmIsDisabledPage(Process, Address))
{
return(STATUS_ACCESS_VIOLATION);
}
/*
* Check for the virtual memory area being deleted.
*/
@ -1438,6 +1443,8 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
if (Entry == 0)
{
SWAPENTRY FakeSwapEntry;
/*
* If the entry is zero (and it can't change because we have
* locked the segment) then we need to load the page.
@ -1448,6 +1455,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
*/
MmSetPageEntrySectionSegment(Segment, &Offset, MAKE_SWAP_SSE(MM_WAIT_ENTRY));
MmUnlockSectionSegment(Segment);
MmCreatePageFileMapping(Process, PAddress, MM_WAIT_ENTRY);
MmUnlockAddressSpace(AddressSpace);
if ((Segment->Flags & MM_PAGEFILE_SEGMENT) ||
@ -1496,6 +1504,9 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
MmUnlockSectionSegment(Segment);
MmDeletePageFileMapping(Process, PAddress, &FakeSwapEntry);
DPRINT("CreateVirtualMapping Page %x Process %p PAddress %p Attributes %x\n",
Page, Process, PAddress, Attributes);
Status = MmCreateVirtualMapping(Process,
PAddress,
Attributes,
@ -1506,6 +1517,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
DPRINT1("Unable to create virtual mapping\n");
KeBugCheck(MEMORY_MANAGEMENT);
}
ASSERT(MmIsPagePresent(Process, PAddress));
MmInsertRmap(Page, Process, Address);
MiSetPageEvent(Process, Address);
@ -2441,7 +2453,7 @@ MmAlterViewAttributes(PMMSUPPORT AddressSpace,
}
}
if (MmIsPagePresent(Process, Address))
if (MmIsPagePresent(Process, Address) || MmIsDisabledPage(Process, Address))
{
MmSetPageProtect(Process, Address,
Protect);