securely access buffers in NtSetContextThread() and NtGetContextThread()
Modified: trunk/reactos/ntoskrnl/ps/debug.c

Modified: trunk/reactos/ntoskrnl/ps/debug.c
--- trunk/reactos/ntoskrnl/ps/debug.c	2005-01-29 03:15:05 UTC (rev 13359)
+++ trunk/reactos/ntoskrnl/ps/debug.c	2005-01-29 12:24:15 UTC (rev 13360)
@@ -186,44 +186,57 @@
 		   OUT PCONTEXT ThreadContext)
 {
   PETHREAD Thread;
-  NTSTATUS Status;
   CONTEXT Context;
   KAPC Apc;
   KEVENT Event;
-  NTSTATUS AStatus;
+  KPROCESSOR_MODE PreviousMode;
+  NTSTATUS Status = STATUS_SUCCESS;
+  
+  PreviousMode = ExGetPreviousMode();
 
-  Status = MmCopyFromCaller(&Context, ThreadContext, sizeof(CONTEXT));
-  if (! NT_SUCCESS(Status))
+  if(PreviousMode != KernelMode)
+  {
+    _SEH_TRY
     {
+      ProbeForWrite(ThreadContext,
+                    sizeof(CONTEXT),
+                    sizeof(ULONG));
+    }
+    _SEH_HANDLE
+    {
+      Status = _SEH_GetExceptionCode();
+    }
+    _SEH_END;
+
+    if(!NT_SUCCESS(Status))
+    {
       return Status;
     }
+  }
+  
   Status = ObReferenceObjectByHandle(ThreadHandle,
                                      THREAD_GET_CONTEXT,
                                      PsThreadType,
-                                     UserMode,
+                                     PreviousMode,
                                      (PVOID*)&Thread,
                                      NULL);
-  if (! NT_SUCCESS(Status))
+  if(NT_SUCCESS(Status))
+  {
+    if(Thread == PsGetCurrentThread())
     {
-      return Status;
-    }
-  if (Thread == PsGetCurrentThread())
-    {
       /*
        * I don't know if trying to get your own context makes much
        * sense but we can handle it more efficently.
        */
 	
       KeTrapFrameToContext(Thread->Tcb.TrapFrame, &Context);
-      Status = STATUS_SUCCESS;
     }
-  else
+    else
     {
       KeInitializeEvent(&Event,
                         NotificationEvent,
-                        FALSE);	
-      AStatus = STATUS_SUCCESS;
-	
+                        FALSE);
+
       KeInitializeApc(&Apc,
                       &Thread->Tcb,
                       OriginalApcEnvironment,
@@ -234,7 +247,7 @@
                       (PVOID)&Context);
       if (!KeInsertQueueApc(&Apc,
 			    (PVOID)&Event,
-			    (PVOID)&AStatus,
+			    (PVOID)&Status,
 			    IO_NO_INCREMENT))
 	{
 	  Status = STATUS_THREAD_IS_TERMINATING;
@@ -243,21 +256,27 @@
 	{
 	  Status = KeWaitForSingleObject(&Event,
 					 0,
-					 UserMode,
+					 KernelMode,
 					 FALSE,
 					 NULL);
-	  if (NT_SUCCESS(Status) && !NT_SUCCESS(AStatus))
-	    {
-	      Status = AStatus;
-	    }
 	}
     }
-  if (NT_SUCCESS(Status))
+    ObDereferenceObject(Thread);
+    
+    if(NT_SUCCESS(Status))
     {
-      Status = MmCopyToCaller(ThreadContext, &Context, sizeof(Context));
+      _SEH_TRY
+      {
+        *ThreadContext = Context;
+      }
+      _SEH_HANDLE
+      {
+        Status = _SEH_GetExceptionCode();
+      }
+      _SEH_END;
     }
-
-  ObDereferenceObject(Thread);
+  }
+  
   return Status;
 }
 
@@ -291,44 +310,58 @@
 		   IN PCONTEXT ThreadContext)
 {
   PETHREAD Thread;
-  NTSTATUS Status;
   KAPC Apc;
   KEVENT Event;
-  NTSTATUS AStatus;
   CONTEXT Context;
-
-  Status = MmCopyFromCaller(&Context, ThreadContext, sizeof(CONTEXT));
-  if (! NT_SUCCESS(Status))
+  KPROCESSOR_MODE PreviousMode;
+  NTSTATUS Status = STATUS_SUCCESS;
+  
+  PreviousMode = ExGetPreviousMode();
+  
+  if(PreviousMode != KernelMode)
+  {
+    _SEH_TRY
     {
+      ProbeForRead(ThreadContext,
+                   sizeof(CONTEXT),
+                   sizeof(ULONG));
+      Context = *ThreadContext;
+      ThreadContext = &Context;
+    }
+    _SEH_HANDLE
+    {
+      Status = _SEH_GetExceptionCode();
+    }
+    _SEH_END;
+    
+    if(!NT_SUCCESS(Status))
+    {
       return Status;
     }
+  }
+
   Status = ObReferenceObjectByHandle(ThreadHandle,
                                      THREAD_SET_CONTEXT,
                                      PsThreadType,
-                                     UserMode,
+                                     PreviousMode,
                                      (PVOID*)&Thread,
                                      NULL);
-  if (!NT_SUCCESS(Status))
+  if(NT_SUCCESS(Status))
+  {
+    if (Thread == PsGetCurrentThread())
     {
-      return Status;
-    }
-
-  if (Thread == PsGetCurrentThread())
-    {
       /*
        * I don't know if trying to set your own context makes much
        * sense but we can handle it more efficently.
        */
 	
       KeContextToTrapFrame(&Context, Thread->Tcb.TrapFrame);
-      Status = STATUS_SUCCESS;
     }
-  else
+    else
     {
       KeInitializeEvent(&Event,
                         NotificationEvent,
                         FALSE);	
-      AStatus = STATUS_SUCCESS;
 	
       KeInitializeApc(&Apc,
                       &Thread->Tcb,
@@ -340,7 +373,7 @@
                       (PVOID)&Context);
       if (!KeInsertQueueApc(&Apc,
 			    (PVOID)&Event,
-			    (PVOID)&AStatus,
+			    (PVOID)&Status,
 			    IO_NO_INCREMENT))
 	{
 	  Status = STATUS_THREAD_IS_TERMINATING;
@@ -349,17 +382,14 @@
 	{
 	  Status = KeWaitForSingleObject(&Event,
 					 0,
-					 UserMode,
+					 KernelMode,
 					 FALSE,
-                                     NULL);
-	  if (NT_SUCCESS(Status) && !NT_SUCCESS(AStatus))
-	    {
-	      Status = AStatus;
-	    }
+                                         NULL);
 	}
     }
-
-  ObDereferenceObject(Thread);
+    ObDereferenceObject(Thread);
+  }
+  
   return Status;
 }