Author: sir_richard
Date: Thu Jul 22 19:08:45 2010
New Revision: 48194
URL:
http://svn.reactos.org/svn/reactos?rev=48194&view=rev
Log:
[NTOS]: Allocate the PEB at a pseudo-random address just like Windows XP SP2 and later, to
prevent certain kinds of exploits.
[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).
Modified:
trunk/reactos/ntoskrnl/mm/ARM3/procsup.c
trunk/reactos/ntoskrnl/mm/procsup.c
Modified: trunk/reactos/ntoskrnl/mm/ARM3/procsup.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/procsup.c…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/procsup.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/procsup.c [iso-8859-1] Thu Jul 22 19:08:45 2010
@@ -17,11 +17,6 @@
#include "../ARM3/miarm.h"
extern MM_SYSTEMSIZE MmSystemSize;
-
-PVOID
-NTAPI
-MiCreatePebOrTeb(PEPROCESS Process,
- PVOID BaseAddress);
/* PRIVATE FUNCTIONS **********************************************************/
@@ -46,6 +41,116 @@
0,
BoundaryAddressMultiple);
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
@@ -415,9 +520,8 @@
//
// 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 @@
//
// 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
Modified: trunk/reactos/ntoskrnl/mm/procsup.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/procsup.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/procsup.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/procsup.c [iso-8859-1] Thu Jul 22 19:08:45 2010
@@ -17,80 +17,6 @@
/* 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)