[NTOS]: Allocate the PEB at a pseudo-random address just like Windows XP SP2 and...
authorSir Richard <sir_richard@svn.reactos.org>
Thu, 22 Jul 2010 19:08:45 +0000 (19:08 +0000)
committerSir Richard <sir_richard@svn.reactos.org>
Thu, 22 Jul 2010 19:08:45 +0000 (19:08 +0000)
[NTOS]: Allocate PEB and TEB using VADs! The user-mode fault handler seems to work fine, and I could find no regressions. This is the beginning of the end for MAREAs for VM allocations (they will remain for sections).

svn path=/trunk/; revision=48194

reactos/ntoskrnl/mm/ARM3/procsup.c
reactos/ntoskrnl/mm/procsup.c

index d2ea798..75c25c6 100644 (file)
 
 extern MM_SYSTEMSIZE MmSystemSize;
 
-PVOID
-NTAPI
-MiCreatePebOrTeb(PEPROCESS Process,
-                 PVOID BaseAddress);
-
 /* PRIVATE FUNCTIONS **********************************************************/
 
 VOID
@@ -48,6 +43,116 @@ MiRosTakeOverPebTebRanges(IN PEPROCESS Process)
     ASSERT(NT_SUCCESS(Status));
 }
 
+NTSTATUS
+NTAPI
+MiCreatePebOrTeb(IN PEPROCESS Process,
+                 IN ULONG Size,
+                 OUT PULONG_PTR Base)
+{
+    PETHREAD Thread = PsGetCurrentThread();
+    PMMVAD_LONG Vad;
+    NTSTATUS Status;
+    ULONG RandomCoeff;
+    ULONG_PTR StartAddress, EndAddress;
+    LARGE_INTEGER CurrentTime;
+    
+    /* Allocate a VAD */
+    Vad = ExAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD_LONG), 'ldaV');
+    if (!Vad) return STATUS_NO_MEMORY;
+    
+    /* Setup the primary flags with the size, and make it commited, private, RW */
+    Vad->u.LongFlags = 0;
+    Vad->u.VadFlags.CommitCharge = BYTES_TO_PAGES(Size);
+    Vad->u.VadFlags.MemCommit = TRUE;
+    Vad->u.VadFlags.PrivateMemory = TRUE;
+    Vad->u.VadFlags.Protection = MM_READWRITE;
+    Vad->u.VadFlags.NoChange = TRUE;
+    
+    /* Setup the secondary flags to make it a secured, writable, long VAD */
+    Vad->u2.LongFlags2 = 0;
+    Vad->u2.VadFlags2.OneSecured = TRUE;
+    Vad->u2.VadFlags2.LongVad = TRUE;
+    Vad->u2.VadFlags2.ReadOnly = FALSE;
+    
+    /* Lock the process address space */
+    KeAcquireGuardedMutex(&Process->AddressCreationLock);
+
+    /* Check if this is a PEB creation */
+    if (Size == sizeof(PEB))
+    {
+        /* Start at the highest valid address */
+        StartAddress = (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1;
+
+        /* Select the random coefficient */
+        KeQueryTickCount(&CurrentTime);
+        CurrentTime.LowPart &= ((64 * _1KB) >> PAGE_SHIFT) - 1;
+        if (CurrentTime.LowPart <= 1) CurrentTime.LowPart = 2;
+        RandomCoeff = CurrentTime.LowPart << PAGE_SHIFT;
+
+        /* Select the highest valid address minus the random coefficient */
+        StartAddress -= RandomCoeff;
+        EndAddress = StartAddress + ROUND_TO_PAGES(Size) - 1;
+
+        /* See if this VA range can be obtained */
+        if (!MiCheckForConflictingNode(StartAddress >> PAGE_SHIFT,
+                                       EndAddress >> PAGE_SHIFT,
+                                       &Process->VadRoot))
+        {
+            /* No conflict, use this address */
+            *Base = StartAddress;
+            goto AfterFound;
+        }
+    }
+    
+    /* For TEBs, or if a PEB location couldn't be found, scan the VAD root */
+    Status = MiFindEmptyAddressRangeDownTree(ROUND_TO_PAGES(Size),
+                                             (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1,
+                                             PAGE_SIZE,
+                                             &Process->VadRoot,
+                                             Base);
+    ASSERT(NT_SUCCESS(Status));
+    
+AfterFound:
+    /* Validate that it came from the VAD ranges */
+    ASSERT(*Base >= (ULONG_PTR)MI_LOWEST_VAD_ADDRESS);
+    
+    /* Build the rest of the VAD now */
+    Vad->StartingVpn = (*Base) >> PAGE_SHIFT;
+    Vad->EndingVpn =  ((*Base) + Size - 1) >> PAGE_SHIFT;
+    Vad->u3.Secured.StartVpn = *Base;
+    Vad->u3.Secured.EndVpn = (Vad->EndingVpn << PAGE_SHIFT) | (PAGE_SIZE - 1);
+    
+    /* FIXME: Should setup VAD bitmap */
+    Status = STATUS_SUCCESS;
+
+    /* Pretend as if we own the working set */
+    MiLockProcessWorkingSet(Process, Thread);
+    
+    /* Insert the VAD */
+    ASSERT(Vad->EndingVpn >= Vad->StartingVpn);
+    Process->VadRoot.NodeHint = Vad;
+    MiInsertNode((PVOID)Vad, &Process->VadRoot);
+    
+    /* Release the working set */
+    MiUnlockProcessWorkingSet(Process, Thread);
+
+    /* Release the address space lock */
+    KeReleaseGuardedMutex(&Process->AddressCreationLock);
+
+    /* Return the status */
+    DPRINT("Allocated PEB/TEB at: 0x%p for %16s\n", *Base, Process->ImageFileName);
+    return Status;
+}
+
+VOID
+NTAPI
+MmDeleteTeb(IN PEPROCESS Process,
+            IN PTEB Teb)
+{
+    /* Oops J */
+    DPRINT("Leaking 4KB at thread exit, this will be fixed later\n");
+}
+
 VOID
 NTAPI
 MmDeleteKernelStack(IN PVOID StackBase,
@@ -415,9 +520,8 @@ MmCreatePeb(IN PEPROCESS Process,
     //
     // Allocate the PEB
     //
-    Peb = MiCreatePebOrTeb(Process,
-                           (PVOID)((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1));
-    if (!Peb) return STATUS_INSUFFICIENT_RESOURCES;
+    Status = MiCreatePebOrTeb(Process, sizeof(PEB), (PULONG_PTR)&Peb);
+    ASSERT(NT_SUCCESS(Status));
 
     //
     // Map NLS Tables
@@ -651,9 +755,8 @@ MmCreateTeb(IN PEPROCESS Process,
     //
     // Allocate the TEB
     //
-    Teb = MiCreatePebOrTeb(Process,
-                           (PVOID)((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1));
-    if (!Teb) return STATUS_INSUFFICIENT_RESOURCES;
+    Status = MiCreatePebOrTeb(Process, sizeof(TEB), (PULONG_PTR)&Teb);
+    ASSERT(NT_SUCCESS(Status));
     
     //
     // Use SEH in case we can't load the TEB
index 1e5bd9a..fce21f5 100644 (file)
@@ -17,80 +17,6 @@ VOID NTAPI MiRosTakeOverPebTebRanges(IN PEPROCESS Process);
 
 /* FUNCTIONS *****************************************************************/
  
-PVOID
-NTAPI
-MiCreatePebOrTeb(PEPROCESS Process,
-                 PVOID BaseAddress)
-{
-    NTSTATUS Status;
-    PMMSUPPORT ProcessAddressSpace = &Process->Vm;
-    PMEMORY_AREA MemoryArea;
-    PHYSICAL_ADDRESS BoundaryAddressMultiple;
-    PVOID AllocatedBase = BaseAddress;
-    BoundaryAddressMultiple.QuadPart = 0;
-
-    /* Acquire the Lock */
-    MmLockAddressSpace(ProcessAddressSpace);
-
-    /*
-     * Create a Peb or Teb.
-     * Loop until it works, decreasing by PAGE_SIZE each time. The logic here
-     * is that a PEB allocation should never fail since the address is free,
-     * while TEB allocation can fail, and we should simply try the address
-     * below. Is there a nicer way of doing this automagically? (ie: findning)
-     * a gap region? -- Alex
-     */
-    do {
-        DPRINT("Trying to allocate: %x\n", AllocatedBase);
-        Status = MmCreateMemoryArea(ProcessAddressSpace,
-                                    MEMORY_AREA_PEB_OR_TEB,
-                                    &AllocatedBase,
-                                    PAGE_SIZE,
-                                    PAGE_READWRITE,
-                                    &MemoryArea,
-                                    TRUE,
-                                    0,
-                                    BoundaryAddressMultiple);
-        AllocatedBase = RVA(AllocatedBase, -PAGE_SIZE);
-    } while (Status != STATUS_SUCCESS);
-
-    /* Initialize the Region */
-    MmInitializeRegion(&MemoryArea->Data.VirtualMemoryData.RegionListHead,
-                       PAGE_SIZE,
-                       MEM_COMMIT,
-                       PAGE_READWRITE);
-
-    /* Reserve the pages */
-    MmReserveSwapPages(PAGE_SIZE);
-
-    /* Unlock Address Space */
-    DPRINT("Returning\n");
-    MmUnlockAddressSpace(ProcessAddressSpace);
-    return RVA(AllocatedBase, PAGE_SIZE);
-}
-
-VOID
-NTAPI
-MmDeleteTeb(PEPROCESS Process,
-            PTEB Teb)
-{
-    PMMSUPPORT ProcessAddressSpace = &Process->Vm;
-    PMEMORY_AREA MemoryArea;
-
-    /* Lock the Address Space */
-    MmLockAddressSpace(ProcessAddressSpace);
-
-    MemoryArea = MmLocateMemoryAreaByAddress(ProcessAddressSpace, (PVOID)Teb);
-    if (MemoryArea)
-    {
-       /* Delete the Teb */
-       MmFreeVirtualMemory(Process, MemoryArea);
-    }
-
-    /* Unlock the Address Space */
-    MmUnlockAddressSpace(ProcessAddressSpace);
-}
-
 NTSTATUS
 NTAPI
 MmInitializeHandBuiltProcess2(IN PEPROCESS Process)