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
|
* Check if this page needs to be mapped COW
|
||||||
*/
|
*/
|
||||||
if ((Segment->WriteCopy) &&
|
if ((Segment->WriteCopy) &&
|
||||||
(Region->Protect == PAGE_READWRITE ||
|
(Region->Protect == PAGE_READWRITE || Region->Protect == PAGE_EXECUTE_READWRITE))
|
||||||
Region->Protect == PAGE_EXECUTE_READWRITE))
|
|
||||||
{
|
{
|
||||||
Attributes = Region->Protect == PAGE_READWRITE ? PAGE_READONLY : PAGE_EXECUTE_READ;
|
Attributes = Region->Protect == PAGE_READWRITE ? PAGE_READONLY : PAGE_EXECUTE_READ;
|
||||||
}
|
}
|
||||||
|
@ -1883,32 +1882,70 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
|
||||||
PMM_SECTION_SEGMENT Segment;
|
PMM_SECTION_SEGMENT Segment;
|
||||||
PFN_NUMBER OldPage;
|
PFN_NUMBER OldPage;
|
||||||
PFN_NUMBER NewPage;
|
PFN_NUMBER NewPage;
|
||||||
NTSTATUS Status;
|
|
||||||
PVOID PAddress;
|
PVOID PAddress;
|
||||||
LARGE_INTEGER Offset;
|
LARGE_INTEGER Offset;
|
||||||
PMM_REGION Region;
|
PMM_REGION Region;
|
||||||
ULONG_PTR Entry;
|
ULONG_PTR Entry;
|
||||||
PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
|
PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
|
||||||
|
BOOLEAN Cow = FALSE;
|
||||||
|
ULONG NewProtect;
|
||||||
|
|
||||||
DPRINT("MmAccessFaultSectionView(%p, %p, %p)\n", AddressSpace, MemoryArea, Address);
|
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. */
|
/* Make sure we have a page mapping for this address. */
|
||||||
Status = MmNotPresentFaultSectionView(AddressSpace, MemoryArea, Address, Locked);
|
if (!MmIsPagePresent(Process, Address))
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
/* This is invalid access ! */
|
NTSTATUS Status = MmNotPresentFaultSectionView(AddressSpace, MemoryArea, Address, Locked);
|
||||||
return Status;
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* This is invalid access ! */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if the page has already been set readwrite
|
* 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);
|
DPRINT("Address 0x%p\n", Address);
|
||||||
return STATUS_SUCCESS;
|
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
|
* Find the offset of the page
|
||||||
*/
|
*/
|
||||||
|
@ -1916,23 +1953,6 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
|
||||||
Offset.QuadPart = (ULONG_PTR)PAddress - MA_GetStartingAddress(MemoryArea)
|
Offset.QuadPart = (ULONG_PTR)PAddress - MA_GetStartingAddress(MemoryArea)
|
||||||
+ MemoryArea->SectionData.ViewOffset;
|
+ 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. */
|
/* Get the page mapping this section offset. */
|
||||||
MmLockSectionSegment(Segment);
|
MmLockSectionSegment(Segment);
|
||||||
Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
|
Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
|
||||||
|
@ -1947,15 +1967,14 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
|
||||||
{
|
{
|
||||||
MmUnlockSectionSegment(Segment);
|
MmUnlockSectionSegment(Segment);
|
||||||
/* This is a private page. We must only change the page protection. */
|
/* This is a private page. We must only change the page protection. */
|
||||||
MmSetPageProtect(Process, PAddress, Region->Protect);
|
MmSetPageProtect(Process, PAddress, NewProtect);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate a page
|
* Allocate a page
|
||||||
*/
|
*/
|
||||||
Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &NewPage);
|
if (!NT_SUCCESS(MmRequestPageMemoryConsumer(MC_USER, TRUE, &NewPage)))
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
KeBugCheck(MEMORY_MANAGEMENT);
|
||||||
}
|
}
|
||||||
|
@ -1978,15 +1997,10 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
|
||||||
/*
|
/*
|
||||||
* Set the PTE to point to the new page
|
* Set the PTE to point to the new page
|
||||||
*/
|
*/
|
||||||
Status = MmCreateVirtualMapping(Process,
|
if (!NT_SUCCESS(MmCreateVirtualMapping(Process, PAddress, NewProtect, NewPage)))
|
||||||
PAddress,
|
|
||||||
Region->Protect,
|
|
||||||
NewPage);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
DPRINT1("MmCreateVirtualMapping failed, unable to create virtual mapping, not out of memory\n");
|
DPRINT1("MmCreateVirtualMapping failed, unable to create virtual mapping, not out of memory\n");
|
||||||
KeBugCheck(MEMORY_MANAGEMENT);
|
KeBugCheck(MEMORY_MANAGEMENT);
|
||||||
return Status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Process)
|
if (Process)
|
||||||
|
|
Loading…
Reference in a new issue