mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
[NTOS:MM] Fix a bit page fault handler with regard to COW sections
This commit is contained in:
parent
a34d9bcfb6
commit
c48580135d
1 changed files with 48 additions and 34 deletions
|
@ -1697,8 +1697,7 @@ MmNotPresentFaultSectionView(PMMSUPPORT AddressSpace,
|
|||
* Check if this page needs to be mapped COW
|
||||
*/
|
||||
if ((Segment->WriteCopy) &&
|
||||
(Region->Protect == PAGE_READWRITE ||
|
||||
Region->Protect == PAGE_EXECUTE_READWRITE))
|
||||
(Region->Protect == PAGE_READWRITE || Region->Protect == PAGE_EXECUTE_READWRITE))
|
||||
{
|
||||
Attributes = Region->Protect == PAGE_READWRITE ? PAGE_READONLY : PAGE_EXECUTE_READ;
|
||||
}
|
||||
|
@ -1883,32 +1882,70 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
|
|||
PMM_SECTION_SEGMENT Segment;
|
||||
PFN_NUMBER OldPage;
|
||||
PFN_NUMBER NewPage;
|
||||
NTSTATUS Status;
|
||||
PVOID PAddress;
|
||||
LARGE_INTEGER Offset;
|
||||
PMM_REGION Region;
|
||||
ULONG_PTR Entry;
|
||||
PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
|
||||
BOOLEAN Cow = FALSE;
|
||||
ULONG NewProtect;
|
||||
|
||||
DPRINT("MmAccessFaultSectionView(%p, %p, %p)\n", AddressSpace, MemoryArea, Address);
|
||||
|
||||
/* Get the region for this address */
|
||||
Region = MmFindRegion((PVOID)MA_GetStartingAddress(MemoryArea),
|
||||
&MemoryArea->SectionData.RegionListHead,
|
||||
Address, NULL);
|
||||
ASSERT(Region != NULL);
|
||||
if (!(Region->Protect & PAGE_IS_WRITABLE))
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
|
||||
/* Make sure we have a page mapping for this address. */
|
||||
Status = MmNotPresentFaultSectionView(AddressSpace, MemoryArea, Address, Locked);
|
||||
if (!NT_SUCCESS(Status))
|
||||
if (!MmIsPagePresent(Process, Address))
|
||||
{
|
||||
/* This is invalid access ! */
|
||||
return Status;
|
||||
NTSTATUS Status = MmNotPresentFaultSectionView(AddressSpace, MemoryArea, Address, Locked);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* This is invalid access ! */
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the page has already been set readwrite
|
||||
*/
|
||||
if (MmGetPageProtect(Process, Address) & PAGE_READWRITE)
|
||||
if (MmGetPageProtect(Process, Address) & (PAGE_READWRITE | PAGE_EXECUTE_READWRITE))
|
||||
{
|
||||
DPRINT("Address 0x%p\n", Address);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Check if we are doing Copy-On-Write */
|
||||
Segment = MemoryArea->SectionData.Segment;
|
||||
Cow = Segment->WriteCopy || (Region->Protect & PAGE_IS_WRITECOPY);
|
||||
|
||||
if (!Cow)
|
||||
{
|
||||
/* Simply update page protection and we're done */
|
||||
MmSetPageProtect(Process, Address, Region->Protect);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Calculate the new protection & check if we should update the region */
|
||||
NewProtect = Region->Protect;
|
||||
if (NewProtect & PAGE_IS_WRITECOPY)
|
||||
{
|
||||
NewProtect &= ~PAGE_IS_WRITECOPY;
|
||||
if (Region->Protect & PAGE_IS_EXECUTABLE)
|
||||
NewProtect |= PAGE_EXECUTE_READWRITE;
|
||||
else
|
||||
NewProtect |= PAGE_READWRITE;
|
||||
MmAlterRegion(AddressSpace, (PVOID)MA_GetStartingAddress(MemoryArea),
|
||||
&MemoryArea->SectionData.RegionListHead,
|
||||
Address, PAGE_SIZE, Region->Type, NewProtect,
|
||||
MmAlterViewAttributes);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the offset of the page
|
||||
*/
|
||||
|
@ -1916,23 +1953,6 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
|
|||
Offset.QuadPart = (ULONG_PTR)PAddress - MA_GetStartingAddress(MemoryArea)
|
||||
+ MemoryArea->SectionData.ViewOffset;
|
||||
|
||||
Segment = MemoryArea->SectionData.Segment;
|
||||
Region = MmFindRegion((PVOID)MA_GetStartingAddress(MemoryArea),
|
||||
&MemoryArea->SectionData.RegionListHead,
|
||||
Address, NULL);
|
||||
ASSERT(Region != NULL);
|
||||
|
||||
/*
|
||||
* Check if we are doing COW
|
||||
*/
|
||||
if (!((Segment->WriteCopy) &&
|
||||
(Region->Protect == PAGE_READWRITE ||
|
||||
Region->Protect == PAGE_EXECUTE_READWRITE)))
|
||||
{
|
||||
DPRINT("Address 0x%p\n", Address);
|
||||
return STATUS_ACCESS_VIOLATION;
|
||||
}
|
||||
|
||||
/* Get the page mapping this section offset. */
|
||||
MmLockSectionSegment(Segment);
|
||||
Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
|
||||
|
@ -1947,15 +1967,14 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
|
|||
{
|
||||
MmUnlockSectionSegment(Segment);
|
||||
/* This is a private page. We must only change the page protection. */
|
||||
MmSetPageProtect(Process, PAddress, Region->Protect);
|
||||
MmSetPageProtect(Process, PAddress, NewProtect);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a page
|
||||
*/
|
||||
Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &NewPage);
|
||||
if (!NT_SUCCESS(Status))
|
||||
if (!NT_SUCCESS(MmRequestPageMemoryConsumer(MC_USER, TRUE, &NewPage)))
|
||||
{
|
||||
KeBugCheck(MEMORY_MANAGEMENT);
|
||||
}
|
||||
|
@ -1978,15 +1997,10 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
|
|||
/*
|
||||
* Set the PTE to point to the new page
|
||||
*/
|
||||
Status = MmCreateVirtualMapping(Process,
|
||||
PAddress,
|
||||
Region->Protect,
|
||||
NewPage);
|
||||
if (!NT_SUCCESS(Status))
|
||||
if (!NT_SUCCESS(MmCreateVirtualMapping(Process, PAddress, NewProtect, NewPage)))
|
||||
{
|
||||
DPRINT1("MmCreateVirtualMapping failed, unable to create virtual mapping, not out of memory\n");
|
||||
KeBugCheck(MEMORY_MANAGEMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (Process)
|
||||
|
|
Loading…
Reference in a new issue