Skip to content

Commit b54e5c6

Browse files
committed
[NTOS:MM] Do not map two pages into hyperspace in MiCopyFromUserPage. CORE-14548
Doing this is not only wrong because it acquires the same spinlock twice, it also completely breaks the TLB flushing logic in MiMapPageInHyperSpace. If the PTE with Offset 1 is still valid when a wrap-around to 0 happens, the TLB flush on wrap-around will not clear the entry for this previous page. After another loop around all hyperspace pages, page 1 is re-used but its TLB entry has not been flushed, which may result into incorrect translation.
1 parent ee8d82f commit b54e5c6

File tree

2 files changed

+7
-9
lines changed

2 files changed

+7
-9
lines changed

ntoskrnl/include/internal/mm.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -757,8 +757,8 @@ MmAccessFault(
757757
NTSTATUS
758758
NTAPI
759759
MiCopyFromUserPage(
760-
PFN_NUMBER NewPage,
761-
PFN_NUMBER OldPage
760+
PFN_NUMBER DestPage,
761+
const VOID *SrcAddress
762762
);
763763

764764
/* process.c *****************************************************************/

ntoskrnl/mm/section.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,23 +1040,21 @@ BOOLEAN MiIsPageFromCache(PMEMORY_AREA MemoryArea,
10401040

10411041
NTSTATUS
10421042
NTAPI
1043-
MiCopyFromUserPage(PFN_NUMBER DestPage, PFN_NUMBER SrcPage)
1043+
MiCopyFromUserPage(PFN_NUMBER DestPage, const VOID *SrcAddress)
10441044
{
10451045
PEPROCESS Process;
1046-
KIRQL Irql, Irql2;
1047-
PVOID DestAddress, SrcAddress;
1046+
KIRQL Irql;
1047+
PVOID DestAddress;
10481048

10491049
Process = PsGetCurrentProcess();
10501050
DestAddress = MiMapPageInHyperSpace(Process, DestPage, &Irql);
1051-
SrcAddress = MiMapPageInHyperSpace(Process, SrcPage, &Irql2);
1052-
if (DestAddress == NULL || SrcAddress == NULL)
1051+
if (DestAddress == NULL)
10531052
{
10541053
return(STATUS_NO_MEMORY);
10551054
}
10561055
ASSERT((ULONG_PTR)DestAddress % PAGE_SIZE == 0);
10571056
ASSERT((ULONG_PTR)SrcAddress % PAGE_SIZE == 0);
10581057
RtlCopyMemory(DestAddress, SrcAddress, PAGE_SIZE);
1059-
MiUnmapPageInHyperSpace(Process, SrcAddress, Irql2);
10601058
MiUnmapPageInHyperSpace(Process, DestAddress, Irql);
10611059
return(STATUS_SUCCESS);
10621060
}
@@ -1781,7 +1779,7 @@ MmAccessFaultSectionView(PMMSUPPORT AddressSpace,
17811779
/*
17821780
* Copy the old page
17831781
*/
1784-
MiCopyFromUserPage(NewPage, OldPage);
1782+
NT_VERIFY(NT_SUCCESS(MiCopyFromUserPage(NewPage, PAddress)));
17851783

17861784
/*
17871785
* Unshare the old page.

0 commit comments

Comments
 (0)