safely access buffers in NtReadVirtualMemory()
Modified: trunk/reactos/ntoskrnl/mm/virtual.c

Modified: trunk/reactos/ntoskrnl/mm/virtual.c
--- trunk/reactos/ntoskrnl/mm/virtual.c	2005-03-14 14:30:43 UTC (rev 14061)
+++ trunk/reactos/ntoskrnl/mm/virtual.c	2005-03-14 15:22:46 UTC (rev 14062)
@@ -463,12 +463,42 @@
                     IN ULONG NumberOfBytesToRead,
                     OUT PULONG NumberOfBytesRead OPTIONAL)
 {
-   NTSTATUS Status;
    PMDL Mdl;
    PVOID SystemAddress;
+   KPROCESSOR_MODE PreviousMode;
    PEPROCESS Process, CurrentProcess;
+   NTSTATUS Status = STATUS_SUCCESS;
+   
+   PAGED_CODE();
+   
+   PreviousMode = ExGetPreviousMode();
+   
+   if(PreviousMode != KernelMode)
+   {
+     _SEH_TRY
+     {
+       ProbeForWrite(Buffer,
+                     NumberOfBytesToRead,
+                     1);
+       if(NumberOfBytesRead != NULL)
+       {
+         ProbeForWrite(NumberOfBytesRead,
+                       sizeof(ULONG),
+                       sizeof(ULONG));
+       }
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+     
+     if(!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+   }
 
-
    DPRINT("NtReadVirtualMemory(ProcessHandle %x, BaseAddress %x, "
           "Buffer %x, NumberOfBytesToRead %d)\n",ProcessHandle,BaseAddress,
           Buffer,NumberOfBytesToRead);
@@ -476,7 +506,7 @@
    Status = ObReferenceObjectByHandle(ProcessHandle,
                                       PROCESS_VM_WRITE,
                                       NULL,
-                                      UserMode,
+                                      PreviousMode,
                                       (PVOID*)(&Process),
                                       NULL);
    if (!NT_SUCCESS(Status))
@@ -488,7 +518,15 @@
 
    if (Process == CurrentProcess)
    {
-      memcpy(Buffer, BaseAddress, NumberOfBytesToRead);
+      _SEH_TRY
+      {
+        RtlCopyMemory(Buffer, BaseAddress, NumberOfBytesToRead);
+      }
+      _SEH_HANDLE
+      {
+        Status = _SEH_GetExceptionCode();
+      }
+      _SEH_END;
    }
    else
    {
@@ -500,39 +538,62 @@
          ObDereferenceObject(Process);
          return(STATUS_NO_MEMORY);
       }
-      MmProbeAndLockPages(Mdl,
-                          UserMode,
-                          IoWriteAccess);
+      _SEH_TRY
+      {
+        MmProbeAndLockPages(Mdl,
+                            PreviousMode,
+                            IoWriteAccess);
+      }
+      _SEH_HANDLE
+      {
+        Status = _SEH_GetExceptionCode();
+      }
+      _SEH_END;
+      
+      if(NT_SUCCESS(Status))
+      {
+        KeAttachProcess(&Process->Pcb);
 
-      KeAttachProcess(&Process->Pcb);
+        SystemAddress = MmGetSystemAddressForMdl(Mdl);
 
-      SystemAddress = MmGetSystemAddressForMdl(Mdl);
+          Status = STATUS_SUCCESS;
+          _SEH_TRY {
+              ProbeForRead(BaseAddress, NumberOfBytesToRead, 1);
+              Status = STATUS_PARTIAL_COPY;
+              RtlCopyMemory(SystemAddress, BaseAddress, NumberOfBytesToRead);
+              Status = STATUS_SUCCESS;
+          } _SEH_HANDLE {
+              if(Status != STATUS_PARTIAL_COPY)
+                  Status = _SEH_GetExceptionCode();
+          } _SEH_END;
 
-        Status = STATUS_SUCCESS;
-        _SEH_TRY {
-            ProbeForRead(BaseAddress, NumberOfBytesToRead, 1);
-            Status = STATUS_PARTIAL_COPY;
-            memcpy(SystemAddress, BaseAddress, NumberOfBytesToRead);
-            Status = STATUS_SUCCESS;
-        } _SEH_HANDLE {
-            if(Status != STATUS_PARTIAL_COPY)
-                Status = _SEH_GetExceptionCode();
-        } _SEH_END;
+        KeDetachProcess();
 
-      KeDetachProcess();
-
-      if (Mdl->MappedSystemVa != NULL)
-      {
-         MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
+        if (Mdl->MappedSystemVa != NULL)
+        {
+           MmUnmapLockedPages(Mdl->MappedSystemVa, Mdl);
+        }
+        MmUnlockPages(Mdl);
       }
-      MmUnlockPages(Mdl);
       ExFreePool(Mdl);
    }
 
    ObDereferenceObject(Process);
 
-   if (NumberOfBytesRead)
-      *NumberOfBytesRead = NumberOfBytesToRead;
+   if((NT_SUCCESS(Status) || Status == STATUS_PARTIAL_COPY) &&
+      NumberOfBytesRead != NULL)
+   {
+     _SEH_TRY
+     {
+       *NumberOfBytesRead = NumberOfBytesToRead;
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+   }
+   
    return(Status);
 }