https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e67b62251f75083acd4fb…
commit e67b62251f75083acd4fb9b98bc13f5ba3a30085
Author: Timo Kreuzer <timo.kreuzer(a)reactos.org>
AuthorDate: Fri Jan 3 10:59:43 2020 +0100
Commit: Timo Kreuzer <timo.kreuzer(a)reactos.org>
CommitDate: Sat Nov 7 20:16:41 2020 +0100
[NTOS:MM] Handle PXE/PPE gaps in MiDeleteVirtualAddresses
---
ntoskrnl/mm/ARM3/virtual.c | 70 ++++++++++++++++++++++++++++++++++++----------
1 file changed, 55 insertions(+), 15 deletions(-)
diff --git a/ntoskrnl/mm/ARM3/virtual.c b/ntoskrnl/mm/ARM3/virtual.c
index f0ab5d08f7b..19eb8a69b01 100644
--- a/ntoskrnl/mm/ARM3/virtual.c
+++ b/ntoskrnl/mm/ARM3/virtual.c
@@ -543,6 +543,12 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
{
PMMPTE PointerPte, PrototypePte, LastPrototypePte;
PMMPDE PointerPde;
+#if (_MI_PAGING_LEVELS >= 3)
+ PMMPPE PointerPpe;
+#endif
+#if (_MI_PAGING_LEVELS >= 4)
+ PMMPPE PointerPxe;
+#endif
MMPTE TempPte;
PEPROCESS CurrentProcess;
KIRQL OldIrql;
@@ -552,10 +558,8 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
/* Get out if this is a fake VAD, RosMm will free the marea pages */
if ((Vad) && (Vad->u.VadFlags.Spare == 1)) return;
- /* Grab the process and PTE/PDE for the address being deleted */
+ /* Get the current process */
CurrentProcess = PsGetCurrentProcess();
- PointerPde = MiAddressToPde(Va);
- PointerPte = MiAddressToPte(Va);
/* Check if this is a section VAD or a VM VAD */
if (!(Vad) || (Vad->u.VadFlags.PrivateMemory) || !(Vad->FirstPrototypePte))
@@ -573,24 +577,59 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
/* In all cases, we don't support fork() yet */
ASSERT(CurrentProcess->CloneRoot == NULL);
- /* Loop the PTE for each VA */
- while (TRUE)
+ /* Loop the PTE for each VA (EndingAddress is inclusive!) */
+ while (Va <= EndingAddress)
{
- /* First keep going until we find a valid PDE */
- while (!PointerPde->u.Long)
+#if (_MI_PAGING_LEVELS >= 4)
+ /* Get the PXE and check if it's valid */
+ PointerPxe = MiAddressToPxe((PVOID)Va);
+ if (!PointerPxe->u.Hard.Valid)
{
- /* There are gaps in the address space */
- AddressGap = TRUE;
+ /* Check for unmapped range and skip it */
+ if (!PointerPxe->u.Long)
+ {
+ /* There are gaps in the address space */
+ AddressGap = TRUE;
- /* Still no valid PDE, try the next 4MB (or whatever) */
- PointerPde++;
+ /* Update Va and continue looping */
+ Va = (ULONG_PTR)MiPxeToAddress(PointerPxe + 1);
+ continue;
+ }
- /* Update the PTE on this new boundary */
- PointerPte = MiPteToAddress(PointerPde);
+ /* Make the PXE valid */
+ MiMakeSystemAddressValid(MiPteToAddress(PointerPxe), CurrentProcess);
+ }
+#endif
+#if (_MI_PAGING_LEVELS >= 3)
+ /* Get the PPE and check if it's valid */
+ PointerPpe = MiAddressToPpe((PVOID)Va);
+ if (!PointerPpe->u.Hard.Valid)
+ {
+ /* Check for unmapped range and skip it */
+ if (!PointerPpe->u.Long)
+ {
+ /* There are gaps in the address space */
+ AddressGap = TRUE;
+
+ /* Update Va and continue looping */
+ Va = (ULONG_PTR)MiPpeToAddress(PointerPpe + 1);
+ continue;
+ }
+
+ /* Make the PPE valid */
+ MiMakeSystemAddressValid(MiPteToAddress(PointerPpe), CurrentProcess);
+ }
+#endif
+ /* Skip invalid PDEs */
+ PointerPde = MiAddressToPde((PVOID)Va);
+ if (!PointerPde->u.Long)
+ {
+ /* There are gaps in the address space */
+ AddressGap = TRUE;
/* Check if all the PDEs are invalid, so there's nothing to free */
- Va = (ULONG_PTR)MiPteToAddress(PointerPte);
- if (Va > EndingAddress) return;
+ Va = (ULONG_PTR)MiPdeToAddress(PointerPde + 1);
+ continue;
}
/* Now check if the PDE is mapped in */
@@ -627,6 +666,7 @@ MiDeleteVirtualAddresses(IN ULONG_PTR Va,
/* Lock the PFN Database while we delete the PTEs */
OldIrql = MiAcquirePfnLock();
+ PointerPte = MiAddressToPte(Va);
do
{
/* Capture the PDE and make sure it exists */