[NTOS/MM]

- Keep the control area as being created through the whole creation process in MmCreateArm3Section
 - Use the segment length to find a suitable place for SEC_BASED sections
 - Properly remove the global section node when deleting a based section
CORE-11900 #resolve

svn path=/trunk/; revision=72472
This commit is contained in:
Jérôme Gardou 2016-08-27 13:17:10 +00:00
parent 5c207cc611
commit 707280b695

View file

@ -1564,6 +1564,9 @@ MiCreatePagingFileMap(OUT PSEGMENT *Segment,
if (AllocationAttributes & SEC_RESERVE) ControlArea->u.Flags.Reserve = 1;
if (AllocationAttributes & SEC_COMMIT) ControlArea->u.Flags.Commit = 1;
/* We just allocated it */
ControlArea->u.Flags.BeingCreated = 1;
/* The subsection follows, write the mask, PTE count and point back to the CA */
Subsection = (PSUBSECTION)(ControlArea + 1);
Subsection->ControlArea = ControlArea;
@ -2565,6 +2568,7 @@ MmCreateArm3Section(OUT PVOID *SectionObject,
/* Set the size here, and read the control area */
Section.SizeOfSection.QuadPart = NewSegment->SizeOfSegment;
ControlArea = NewSegment->ControlArea;
ASSERT(ControlArea->u.Flags.BeingCreated == 1);
}
/* Did we already have a segment? */
@ -2663,6 +2667,60 @@ MmCreateArm3Section(OUT PVOID *SectionObject,
ASSERT(KernelCall == FALSE);
NewSection->u.Flags.UserReference = TRUE;
/* Is this a "based" allocation, in which all mappings are identical? */
if (AllocationAttributes & SEC_BASED)
{
/* Lock the VAD tree during the search */
KeAcquireGuardedMutex(&MmSectionBasedMutex);
/* Is it a brand new ControArea ? */
if (ControlArea->u.Flags.BeingCreated == 1)
{
ASSERT(ControlArea->u.Flags.Based == 1);
/* Then we must find a global address, top-down */
Status = MiFindEmptyAddressRangeDownBasedTree((SIZE_T)ControlArea->Segment->SizeOfSegment,
(ULONG_PTR)MmHighSectionBase,
_64K,
&MmSectionBasedRoot,
(ULONG_PTR*)&ControlArea->Segment->BasedAddress);
if (!NT_SUCCESS(Status))
{
/* No way to find a valid range. */
KeReleaseGuardedMutex(&MmSectionBasedMutex);
ControlArea->u.Flags.Based = 0;
NewSection->u.Flags.Based = 0;
ObDereferenceObject(NewSection);
return Status;
}
/* Compute the ending address and insert it into the VAD tree */
NewSection->Address.StartingVpn = (ULONG_PTR)ControlArea->Segment->BasedAddress;
NewSection->Address.EndingVpn = NewSection->Address.StartingVpn + NewSection->SizeOfSection.LowPart - 1;
MiInsertBasedSection(NewSection);
}
else
{
/* FIXME : Should we deny section creation if SEC_BASED is not set ? Can we have two different section objects on the same based address ? Investigate !*/
ASSERT(FALSE);
}
KeReleaseGuardedMutex(&MmSectionBasedMutex);
}
/* The control area is not being created anymore */
if (ControlArea->u.Flags.BeingCreated == 1)
{
/* Acquire the PFN lock while we set control area flags */
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
/* Take off the being created flag, and then release the lock */
ControlArea->u.Flags.BeingCreated = 0;
NewSection->u.Flags.BeingCreated = 0;
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
}
/* Migrate the attribute into a flag */
if (AllocationAttributes & SEC_NO_CHANGE) NewSection->u.Flags.NoChange = TRUE;
@ -2672,40 +2730,6 @@ MmCreateArm3Section(OUT PVOID *SectionObject,
NewSection->u.Flags.CopyOnWrite = TRUE;
}
/* Is this a "based" allocation, in which all mappings are identical? */
if (AllocationAttributes & SEC_BASED)
{
/* Convert the flag, and make sure the section isn't too big */
NewSection->u.Flags.Based = TRUE;
if ((ULONGLONG)NewSection->SizeOfSection.QuadPart >
(ULONG_PTR)MmHighSectionBase)
{
DPRINT1("BASED section is too large\n");
ObDereferenceObject(NewSection);
return STATUS_NO_MEMORY;
}
/* Lock the VAD tree during the search */
KeAcquireGuardedMutex(&MmSectionBasedMutex);
/* Find an address top-down */
Status = MiFindEmptyAddressRangeDownBasedTree(NewSection->SizeOfSection.LowPart,
(ULONG_PTR)MmHighSectionBase,
_64K,
&MmSectionBasedRoot,
&NewSection->Address.StartingVpn);
ASSERT(NT_SUCCESS(Status));
/* Compute the ending address and insert it into the VAD tree */
NewSection->Address.EndingVpn = NewSection->Address.StartingVpn +
NewSection->SizeOfSection.LowPart -
1;
MiInsertBasedSection(NewSection);
/* Finally release the lock */
KeReleaseGuardedMutex(&MmSectionBasedMutex);
}
/* Write down if this was a kernel call */
ControlArea->u.Flags.WasPurged |= KernelCall;
ASSERT(ControlArea->u.Flags.WasPurged == FALSE);
@ -3142,6 +3166,14 @@ MiDeleteARM3Section(PVOID ObjectBody)
SectionObject = (PSECTION)ObjectBody;
if (SectionObject->u.Flags.Based == 1)
{
/* Remove the node from the global section address tree */
KeAcquireGuardedMutex(&MmSectionBasedMutex);
MiRemoveNode(&SectionObject->Address, &MmSectionBasedRoot);
KeReleaseGuardedMutex(&MmSectionBasedMutex);
}
/* Lock the PFN database */
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);