[NTOS/MM] Introduce MmMapViewInSystemSpaceEx

This commit is contained in:
Jérôme Gardou 2020-10-27 17:36:18 +01:00
parent 4f6fd6c42b
commit f1631b44e1
3 changed files with 71 additions and 28 deletions

View file

@ -1313,6 +1313,16 @@ VOID
NTAPI NTAPI
MmFreeSectionSegments(PFILE_OBJECT FileObject); MmFreeSectionSegments(PFILE_OBJECT FileObject);
/* Exported from NT 6.2 Onward. We keep it internal. */
NTSTATUS
NTAPI
MmMapViewInSystemSpaceEx (
_In_ PVOID Section,
_Outptr_result_bytebuffer_ (*ViewSize) PVOID *MappedBase,
_Inout_ PSIZE_T ViewSize,
_Inout_ PLARGE_INTEGER SectionOffset
);
/* sysldr.c ******************************************************************/ /* sysldr.c ******************************************************************/
VOID VOID

View file

@ -416,12 +416,16 @@ NTSTATUS
NTAPI NTAPI
MiAddMappedPtes(IN PMMPTE FirstPte, MiAddMappedPtes(IN PMMPTE FirstPte,
IN PFN_NUMBER PteCount, IN PFN_NUMBER PteCount,
IN PCONTROL_AREA ControlArea) IN PCONTROL_AREA ControlArea,
IN PLARGE_INTEGER SectionOffset)
{ {
MMPTE TempPte; MMPTE TempPte;
PMMPTE PointerPte, ProtoPte, LastProtoPte, LastPte; PMMPTE PointerPte, ProtoPte, LastProtoPte, LastPte;
PSUBSECTION Subsection; PSUBSECTION Subsection;
/* Mapping at offset not supported yet */
ASSERT(SectionOffset->QuadPart == 0);
/* ARM3 doesn't support this yet */ /* ARM3 doesn't support this yet */
ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0); ASSERT(ControlArea->u.Flags.GlobalOnlyPerSession == 0);
ASSERT(ControlArea->u.Flags.Rom == 0); ASSERT(ControlArea->u.Flags.Rom == 0);
@ -1052,11 +1056,13 @@ NTAPI
MiMapViewInSystemSpace(IN PVOID Section, MiMapViewInSystemSpace(IN PVOID Section,
IN PMMSESSION Session, IN PMMSESSION Session,
OUT PVOID *MappedBase, OUT PVOID *MappedBase,
IN OUT PSIZE_T ViewSize) IN OUT PSIZE_T ViewSize,
IN PLARGE_INTEGER SectionOffset)
{ {
PVOID Base; PVOID Base;
PCONTROL_AREA ControlArea; PCONTROL_AREA ControlArea;
ULONG Buckets, SectionSize; ULONG Buckets;
LONGLONG SectionSize;
NTSTATUS Status; NTSTATUS Status;
PAGED_CODE(); PAGED_CODE();
@ -1073,13 +1079,23 @@ MiMapViewInSystemSpace(IN PVOID Section,
ASSERT(NT_SUCCESS(Status)); ASSERT(NT_SUCCESS(Status));
/* Get the section size at creation time */ /* Get the section size at creation time */
SectionSize = ((PSECTION)Section)->SizeOfSection.LowPart; SectionSize = ((PSECTION)Section)->SizeOfSection.QuadPart;
/* If the caller didn't specify a view size, assume the whole section */ /* If the caller didn't specify a view size, assume until the end of the section */
if (!(*ViewSize)) *ViewSize = SectionSize; if (!(*ViewSize))
{
/* Check for overflow first */
if ((SectionSize - SectionOffset->QuadPart) > SIZE_T_MAX)
{
DPRINT1("Section end is too far away from the specified offset.\n");
MiDereferenceControlArea(ControlArea);
return STATUS_INVALID_VIEW_SIZE;
}
*ViewSize = SectionSize - SectionOffset->QuadPart;
}
/* Check if the caller wanted a larger section than the view */ /* Check if the caller wanted a larger section than the view */
if (*ViewSize > SectionSize) if (SectionOffset->QuadPart + *ViewSize > SectionSize)
{ {
/* Fail */ /* Fail */
DPRINT1("View is too large\n"); DPRINT1("View is too large\n");
@ -1129,7 +1145,8 @@ MiMapViewInSystemSpace(IN PVOID Section,
/* Create the actual prototype PTEs for this mapping */ /* Create the actual prototype PTEs for this mapping */
Status = MiAddMappedPtes(MiAddressToPte(Base), Status = MiAddMappedPtes(MiAddressToPte(Base),
BYTES_TO_PAGES(*ViewSize), BYTES_TO_PAGES(*ViewSize),
ControlArea); ControlArea,
SectionOffset);
ASSERT(NT_SUCCESS(Status)); ASSERT(NT_SUCCESS(Status));
/* Return the base adress of the mapping and success */ /* Return the base adress of the mapping and success */
@ -3016,6 +3033,7 @@ MmMapViewInSessionSpace(IN PVOID Section,
IN OUT PSIZE_T ViewSize) IN OUT PSIZE_T ViewSize)
{ {
PAGED_CODE(); PAGED_CODE();
LARGE_INTEGER SectionOffset;
// HACK // HACK
if (MiIsRosSectionObject(Section)) if (MiIsRosSectionObject(Section))
@ -3032,10 +3050,12 @@ MmMapViewInSessionSpace(IN PVOID Section,
/* Use the system space API, but with the session view instead */ /* Use the system space API, but with the session view instead */
ASSERT(MmIsAddressValid(MmSessionSpace) == TRUE); ASSERT(MmIsAddressValid(MmSessionSpace) == TRUE);
SectionOffset.QuadPart = 0;
return MiMapViewInSystemSpace(Section, return MiMapViewInSystemSpace(Section,
&MmSessionSpace->Session, &MmSessionSpace->Session,
MappedBase, MappedBase,
ViewSize); ViewSize,
&SectionOffset);
} }
/* /*

View file

@ -88,7 +88,8 @@ NTAPI
MiMapViewInSystemSpace(IN PVOID Section, MiMapViewInSystemSpace(IN PVOID Section,
IN PVOID Session, IN PVOID Session,
OUT PVOID *MappedBase, OUT PVOID *MappedBase,
IN OUT PSIZE_T ViewSize); IN OUT PSIZE_T ViewSize,
IN PLARGE_INTEGER SectionOffset);
NTSTATUS NTSTATUS
NTAPI NTAPI
@ -3832,7 +3833,7 @@ MmMapViewOfSegment(PMMSUPPORT AddressSpace,
PVOID* BaseAddress, PVOID* BaseAddress,
SIZE_T ViewSize, SIZE_T ViewSize,
ULONG Protect, ULONG Protect,
ULONG ViewOffset, LONGLONG ViewOffset,
ULONG AllocationType) ULONG AllocationType)
{ {
PMEMORY_AREA MArea; PMEMORY_AREA MArea;
@ -4417,7 +4418,6 @@ MmMapViewOfSection(IN PVOID SectionObject,
{ {
PSECTION Section; PSECTION Section;
PMMSUPPORT AddressSpace; PMMSUPPORT AddressSpace;
ULONG ViewOffset;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
BOOLEAN NotAtBase = FALSE; BOOLEAN NotAtBase = FALSE;
@ -4530,7 +4530,7 @@ MmMapViewOfSection(IN PVOID SectionObject,
Section, Section,
&SectionSegments[i], &SectionSegments[i],
&SBaseAddress, &SBaseAddress,
SectionSegments[i].Length.LowPart, SectionSegments[i].Length.QuadPart,
SectionSegments[i].Protection, SectionSegments[i].Protection,
0, 0,
0); 0);
@ -4548,6 +4548,7 @@ MmMapViewOfSection(IN PVOID SectionObject,
else else
{ {
PMM_SECTION_SEGMENT Segment = (PMM_SECTION_SEGMENT)Section->Segment; PMM_SECTION_SEGMENT Segment = (PMM_SECTION_SEGMENT)Section->Segment;
LONGLONG ViewOffset;
/* check for write access */ /* check for write access */
if ((Protect & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE)) && if ((Protect & (PAGE_READWRITE|PAGE_EXECUTE_READWRITE)) &&
@ -4577,7 +4578,7 @@ MmMapViewOfSection(IN PVOID SectionObject,
} }
else else
{ {
ViewOffset = SectionOffset->u.LowPart; ViewOffset = SectionOffset->QuadPart;
} }
if ((ViewOffset % PAGE_SIZE) != 0) if ((ViewOffset % PAGE_SIZE) != 0)
@ -4588,11 +4589,11 @@ MmMapViewOfSection(IN PVOID SectionObject,
if ((*ViewSize) == 0) if ((*ViewSize) == 0)
{ {
(*ViewSize) = Section->SizeOfSection.u.LowPart - ViewOffset; (*ViewSize) = Section->SizeOfSection.QuadPart - ViewOffset;
} }
else if (((*ViewSize)+ViewOffset) > Section->SizeOfSection.u.LowPart) else if (((*ViewSize)+ViewOffset) > Section->SizeOfSection.QuadPart)
{ {
(*ViewSize) = Section->SizeOfSection.u.LowPart - ViewOffset; (*ViewSize) = MIN(Section->SizeOfSection.QuadPart - ViewOffset, SIZE_T_MAX - PAGE_SIZE);
} }
*ViewSize = PAGE_ROUND_UP(*ViewSize); *ViewSize = PAGE_ROUND_UP(*ViewSize);
@ -4756,7 +4757,23 @@ MmMapViewInSystemSpace (IN PVOID SectionObject,
OUT PVOID * MappedBase, OUT PVOID * MappedBase,
IN OUT PSIZE_T ViewSize) IN OUT PSIZE_T ViewSize)
{ {
PSECTION Section; LARGE_INTEGER SectionOffset;
SectionOffset.QuadPart = 0;
return MmMapViewInSystemSpaceEx(SectionObject, MappedBase, ViewSize, &SectionOffset);
}
NTSTATUS
NTAPI
MmMapViewInSystemSpaceEx (
_In_ PVOID SectionObject,
_Outptr_result_bytebuffer_ (*ViewSize) PVOID *MappedBase,
_Inout_ PSIZE_T ViewSize,
_Inout_ PLARGE_INTEGER SectionOffset
)
{
PSECTION Section = SectionObject;
PMM_SECTION_SEGMENT Segment; PMM_SECTION_SEGMENT Segment;
PMMSUPPORT AddressSpace; PMMSUPPORT AddressSpace;
NTSTATUS Status; NTSTATUS Status;
@ -4767,10 +4784,11 @@ MmMapViewInSystemSpace (IN PVOID SectionObject,
return MiMapViewInSystemSpace(SectionObject, return MiMapViewInSystemSpace(SectionObject,
&MmSession, &MmSession,
MappedBase, MappedBase,
ViewSize); ViewSize,
SectionOffset);
} }
DPRINT("MmMapViewInSystemSpace() called\n"); DPRINT("MmMapViewInSystemSpaceEx() called\n");
Section = SectionObject; Section = SectionObject;
Segment = (PMM_SECTION_SEGMENT)Section->Segment; Segment = (PMM_SECTION_SEGMENT)Section->Segment;
@ -4780,25 +4798,20 @@ MmMapViewInSystemSpace (IN PVOID SectionObject,
MmLockAddressSpace(AddressSpace); MmLockAddressSpace(AddressSpace);
if ((*ViewSize) == 0) if ((*ViewSize == 0) || ((SectionOffset->QuadPart + *ViewSize) > Section->SizeOfSection.QuadPart))
{ {
(*ViewSize) = Section->SizeOfSection.u.LowPart; *ViewSize = MIN((Section->SizeOfSection.QuadPart - SectionOffset->QuadPart), SIZE_T_MAX);
}
else if ((*ViewSize) > Section->SizeOfSection.u.LowPart)
{
(*ViewSize) = Section->SizeOfSection.u.LowPart;
} }
MmLockSectionSegment(Segment); MmLockSectionSegment(Segment);
Status = MmMapViewOfSegment(AddressSpace, Status = MmMapViewOfSegment(AddressSpace,
Section, Section,
Segment, Segment,
MappedBase, MappedBase,
*ViewSize, *ViewSize,
PAGE_READWRITE, PAGE_READWRITE,
0, SectionOffset->QuadPart,
0); 0);
MmUnlockSectionSegment(Segment); MmUnlockSectionSegment(Segment);