Likely fix for bug 5600:
authorSir Richard <sir_richard@svn.reactos.org>
Sun, 12 Sep 2010 19:10:27 +0000 (19:10 +0000)
committerSir Richard <sir_richard@svn.reactos.org>
Sun, 12 Sep 2010 19:10:27 +0000 (19:10 +0000)
[NTOS]: Using IsBadRead/CodePtr, it's possible for user-mode code to generate cases where we *think* this is an ARM3-managed piece of VA, which will always have a VAD (Since we only manage the PEB/TEB), but actually it's a bogus VA-looking address that is actually invalid. We didn't consider this case. We now implement the same code Windows normally would also handle, when the VA is bogus, and accept that no VAD might be found, so MM_NOACCESS is returned and thus an access violation sent to the caller. In the case of the IsBad...Ptr, this function would then return TRUE, as the caller expects.

svn path=/trunk/; revision=48759

reactos/ntoskrnl/mm/ARM3/pagfault.c

index 8627cde..c391a0a 100644 (file)
@@ -42,9 +42,14 @@ MiCheckVirtualAddress(IN PVOID VirtualAddress,
         return MmSharedUserDataPte;
     }
     
-    /* Find the VAD, it must exist, since we only handle PEB/TEB */
+    /* Find the VAD, it might not exist if the address is bogus */
     Vad = MiLocateAddress(VirtualAddress);
-    ASSERT(Vad);
+    if (!Vad)
+    {
+        /* Bogus virtual address */
+        *ProtectCode = MM_NOACCESS;
+        return NULL;
+    }
     
     /* This must be a TEB/PEB VAD */
     ASSERT(Vad->u.VadFlags.PrivateMemory == TRUE);
@@ -726,8 +731,23 @@ MmArmAccessFault(IN BOOLEAN StoreInstruction,
 
     /* Check if this address range belongs to a valid allocation (VAD) */
     ProtoPte = MiCheckVirtualAddress(Address, &ProtectionCode, &Vad);
-    ASSERT(ProtectionCode != MM_NOACCESS);
-
+    if (ProtectionCode == MM_NOACCESS)
+    {
+        /* This is a bogus VA */
+        Status = STATUS_ACCESS_VIOLATION;
+        
+        /* Could be a not-yet-mapped paged pool page table */
+#if (_MI_PAGING_LEVELS == 2) 
+        MiCheckPdeForPagedPool(Address);
+#endif
+        /* See if that fixed it */
+        if (PointerPte->u.Hard.Valid == 1) Status = STATUS_SUCCESS;
+        
+        /* Return the status */
+        MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
+        return Status;
+    }
+    
     /* Did we get a prototype PTE back? */
     if (!ProtoPte)
     {