[NTOS]
authorStefan Ginsberg <stefanginsberg@gmail.com>
Thu, 15 Oct 2015 12:56:19 +0000 (12:56 +0000)
committerStefan Ginsberg <stefanginsberg@gmail.com>
Thu, 15 Oct 2015 12:56:19 +0000 (12:56 +0000)
Isolate KD a bit by replacing Rtl* memory routines with internal versions. Lets one put breakpoints inside kernel memcpy/memset without making KD very, very sad. Fix MmDbgCopyMemory to also not use RtlCopyMemory -- there is no need for it since it only performs 1-to-8 byte copies anyway. Minor fixes in the print/prompt routines.

svn path=/trunk/; revision=69539

reactos/ntoskrnl/include/internal/kd64.h
reactos/ntoskrnl/kd64/kdapi.c
reactos/ntoskrnl/kd64/kdprint.c
reactos/ntoskrnl/kd64/kdtrap.c
reactos/ntoskrnl/mm/ARM3/session.c

index 38534c1..7957823 100644 (file)
@@ -351,6 +351,24 @@ KdpCopyMemoryChunks(
     OUT PULONG ActualSize OPTIONAL
 );
 
+//
+// Internal memory handling routines for KD isolation
+//
+VOID
+NTAPI
+KdpMoveMemory(
+    IN PVOID Destination,
+    IN PVOID Source,
+    IN SIZE_T Length
+);
+
+VOID
+NTAPI
+KdpZeroMemory(
+    IN PVOID Destination,
+    IN SIZE_T Length
+);
+
 //
 // Low Level Support Routines for the KD API
 //
index bc2de45..f0415ba 100644 (file)
 
 /* PRIVATE FUNCTIONS *********************************************************/
 
+VOID
+NTAPI
+KdpMoveMemory(IN PVOID Destination,
+              IN PVOID Source,
+              IN SIZE_T Length)
+{
+    PCHAR DestinationBytes, SourceBytes;
+
+    /* Copy the buffers 1 byte at a time */
+    DestinationBytes = Destination;
+    SourceBytes = Source;
+    while (Length--) *DestinationBytes++ = *SourceBytes++;
+}
+
+VOID
+NTAPI
+KdpZeroMemory(IN PVOID Destination,
+              IN SIZE_T Length)
+{
+    PCHAR DestinationBytes;
+
+    /* Zero the buffer 1 byte at a time */
+    DestinationBytes = Destination;
+    while (Length--) *DestinationBytes++ = 0;
+}
+
 NTSTATUS
 NTAPI
 KdpCopyMemoryChunks(IN ULONG64 Address,
@@ -368,7 +394,7 @@ KdpSetCommonState(IN ULONG NewState,
     WaitStateChange->ProgramCounter = (ULONG64)(LONG_PTR)KeGetContextPc(Context);
 
     /* Zero out the entire Control Report */
-    RtlZeroMemory(&WaitStateChange->AnyControlReport,
+    KdpZeroMemory(&WaitStateChange->AnyControlReport,
                   sizeof(DBGKD_ANY_CONTROL_REPORT));
 
     /* Now copy the instruction stream and set the count */
@@ -402,7 +428,9 @@ NTAPI
 KdpSysGetVersion(IN PDBGKD_GET_VERSION64 Version)
 {
     /* Copy the version block */
-    RtlCopyMemory(Version, &KdVersionBlock, sizeof(DBGKD_GET_VERSION64));
+    KdpMoveMemory(Version,
+                  &KdVersionBlock,
+                  sizeof(DBGKD_GET_VERSION64));
 }
 
 VOID
@@ -711,7 +739,9 @@ KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State,
         }
 
         /* Copy it over to the debugger */
-        RtlCopyMemory(Data->Buffer, TargetContext, sizeof(CONTEXT));
+        KdpMoveMemory(Data->Buffer,
+                      TargetContext,
+                      sizeof(CONTEXT));
         Data->Length = sizeof(CONTEXT);
 
         /* Let the debugger set the context now */
@@ -765,7 +795,9 @@ KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State,
         }
 
         /* Copy the new context to it */
-        RtlCopyMemory(TargetContext, Data->Buffer, sizeof(CONTEXT));
+        KdpMoveMemory(TargetContext,
+                      Data->Buffer,
+                      sizeof(CONTEXT));
 
         /* Finish up */
         State->ReturnStatus = STATUS_SUCCESS;
@@ -819,7 +851,7 @@ KdpGetContextEx(IN PDBGKD_MANIPULATE_STATE64 State,
         }
 
         /* Copy what is requested */
-        RtlCopyMemory(Data->Buffer,
+        KdpMoveMemory(Data->Buffer,
                       (PVOID)((ULONG_PTR)TargetContext + ContextEx->Offset),
                       ContextEx->ByteCount);
 
@@ -883,7 +915,7 @@ KdpSetContextEx(IN PDBGKD_MANIPULATE_STATE64 State,
         }
 
         /* Copy what is requested */
-        RtlCopyMemory((PVOID)((ULONG_PTR)TargetContext + ContextEx->Offset),
+        KdpMoveMemory((PVOID)((ULONG_PTR)TargetContext + ContextEx->Offset),
                       Data->Buffer,
                       ContextEx->ByteCount);
 
@@ -1639,7 +1671,7 @@ KdpReportCommandStringStateChange(IN PSTRING NameString,
         KdpSetContextState(&WaitStateChange, Context);
 
         /* Clear the command string structure */
-        RtlZeroMemory(&WaitStateChange.u.CommandString,
+        KdpZeroMemory(&WaitStateChange.u.CommandString,
                       sizeof(DBGKD_COMMAND_STRING));
 
         /* Normalize name string to max */
@@ -1709,15 +1741,22 @@ KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord,
         /* Build the architecture common parts of the message */
         KdpSetCommonState(DbgKdExceptionStateChange, Context, &WaitStateChange);
 
-        /* Copy the Exception Record and set First Chance flag */
 #if !defined(_WIN64)
+
+        /* Convert it and copy it over */
         ExceptionRecord32To64((PEXCEPTION_RECORD32)ExceptionRecord,
                               &WaitStateChange.u.Exception.ExceptionRecord);
+
 #else
-        RtlCopyMemory(&WaitStateChange.u.Exception.ExceptionRecord,
+
+        /* Just copy it directly, no need to convert */
+        KdpMoveMemory(&WaitStateChange.u.Exception.ExceptionRecord,
                       ExceptionRecord,
                       sizeof(EXCEPTION_RECORD));
+
 #endif
+
+        /* Set the First Chance flag */
         WaitStateChange.u.Exception.FirstChance = !SecondChanceException;
 
         /* Now finish creating the structure */
index 5b6959b..9fccf74 100644 (file)
@@ -21,12 +21,15 @@ KdpPrintString(IN PSTRING Output)
 {
     STRING Data, Header;
     DBGKD_DEBUG_IO DebugIo;
-    USHORT Length = Output->Length;
+    USHORT Length;
 
     /* Copy the string */
-    RtlMoveMemory(KdpMessageBuffer, Output->Buffer, Length);
+    KdpMoveMemory(KdpMessageBuffer,
+                  Output->Buffer,
+                  Output->Length);
 
     /* Make sure we don't exceed the KD Packet size */
+    Length = Output->Length;
     if ((sizeof(DBGKD_DEBUG_IO) + Length) > PACKET_MAX_SIZE)
     {
         /* Normalize length */
@@ -59,15 +62,16 @@ KdpPromptString(IN PSTRING PromptString,
 {
     STRING Data, Header;
     DBGKD_DEBUG_IO DebugIo;
-    ULONG Length = PromptString->Length;
+    ULONG Length;
     KDSTATUS Status;
 
     /* Copy the string to the message buffer */
-    RtlCopyMemory(KdpMessageBuffer,
+    KdpMoveMemory(KdpMessageBuffer,
                   PromptString->Buffer,
                   PromptString->Length);
 
     /* Make sure we don't exceed the KD Packet size */
+    Length = PromptString->Length;
     if ((sizeof(DBGKD_DEBUG_IO) + Length) > PACKET_MAX_SIZE)
     {
         /* Normalize length */
@@ -84,7 +88,7 @@ KdpPromptString(IN PSTRING PromptString,
     Header.Buffer = (PCHAR)&DebugIo;
 
     /* Build the data */
-    Data.Length = PromptString->Length;
+    Data.Length = Length;
     Data.Buffer = KdpMessageBuffer;
 
     /* Send the packet */
@@ -111,10 +115,13 @@ KdpPromptString(IN PSTRING PromptString,
     } while (Status != KdPacketReceived);
 
     /* Don't copy back a larger response than there is room for */
-    Length = min(Length, ResponseString->MaximumLength);
+    Length = min(Length,
+                 ResponseString->MaximumLength);
 
     /* Copy back the string and return the length */
-    RtlCopyMemory(ResponseString->Buffer, KdpMessageBuffer, Length);
+    KdpMoveMemory(ResponseString->Buffer,
+                  KdpMessageBuffer,
+                  Length);
     ResponseString->Length = (USHORT)Length;
 
     /* Success; we don't need to resend */
@@ -141,7 +148,7 @@ KdpCommandString(IN PSTRING NameString,
 
     /* Save the CPU Control State and save the context */
     KiSaveProcessorControlState(&Prcb->ProcessorState);
-    RtlCopyMemory(&Prcb->ProcessorState.ContextFrame,
+    KdpMoveMemory(&Prcb->ProcessorState.ContextFrame,
                   ContextRecord,
                   sizeof(CONTEXT));
 
@@ -151,7 +158,7 @@ KdpCommandString(IN PSTRING NameString,
                                       &Prcb->ProcessorState.ContextFrame);
 
     /* Restore the processor state */
-    RtlCopyMemory(ContextRecord,
+    KdpMoveMemory(ContextRecord,
                   &Prcb->ProcessorState.ContextFrame,
                   sizeof(CONTEXT));
     KiRestoreProcessorControlState(&Prcb->ProcessorState);
@@ -181,7 +188,7 @@ KdpSymbol(IN PSTRING DllPath,
 
     /* Save the CPU Control State and save the context */
     KiSaveProcessorControlState(&Prcb->ProcessorState);
-    RtlCopyMemory(&Prcb->ProcessorState.ContextFrame,
+    KdpMoveMemory(&Prcb->ProcessorState.ContextFrame,
                   ContextRecord,
                   sizeof(CONTEXT));
 
@@ -192,7 +199,7 @@ KdpSymbol(IN PSTRING DllPath,
                                     &Prcb->ProcessorState.ContextFrame);
 
     /* Restore the processor state */
-    RtlCopyMemory(ContextRecord,
+    KdpMoveMemory(ContextRecord,
                   &Prcb->ProcessorState.ContextFrame,
                   sizeof(CONTEXT));
     KiRestoreProcessorControlState(&Prcb->ProcessorState);
@@ -216,38 +223,48 @@ KdpPrompt(IN LPSTR PromptString,
     PVOID CapturedPrompt, CapturedResponse;
 
     /* Normalize the lengths */
-    PromptLength = min(PromptLength, 512);
-    MaximumResponseLength = min(MaximumResponseLength, 512);
+    PromptLength = min(PromptLength,
+                       512);
+    MaximumResponseLength = min(MaximumResponseLength,
+                                512);
 
     /* Check if we need to verify the string */
     if (PreviousMode != KernelMode)
     {
-        /* Capture user-mode buffers */
+        /* Handle user-mode buffers safely */
         _SEH2_TRY
         {
-            ProbeForRead(PromptString, PromptLength, 1);
-            CapturedPrompt = alloca(512);
-            RtlMoveMemory(CapturedPrompt, PromptString, PromptLength);
+            /* Probe the prompt */
+            ProbeForRead(PromptString,
+                         PromptLength,
+                         1);
+
+            /* Capture prompt */
+            CapturedPrompt = _alloca(PromptLength);
+            KdpMoveMemory(CapturedPrompt,
+                          PromptString,
+                          PromptLength);
             PromptString = CapturedPrompt;
 
-            ProbeForWrite(ResponseString, MaximumResponseLength, 1);
-            CapturedResponse = alloca(512);
+            /* Probe and make room for response */
+            ProbeForWrite(ResponseString,
+                          MaximumResponseLength,
+                          1);
+            CapturedResponse = _alloca(MaximumResponseLength);
+            ResponseString = CapturedResponse;
         }
         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
         {
+            /* Bad string pointer, bail out  */
             _SEH2_YIELD(return 0);
         }
         _SEH2_END;
     }
-    else
-    {
-        CapturedResponse = ResponseString;
-    }
 
     /* Setup the prompt and response  buffers */
     PromptBuffer.Buffer = PromptString;
     PromptBuffer.Length = PromptLength;
-    ResponseBuffer.Buffer = CapturedResponse;
+    ResponseBuffer.Buffer = ResponseString;
     ResponseBuffer.Length = 0;
     ResponseBuffer.MaximumLength = MaximumResponseLength;
 
@@ -274,10 +291,14 @@ KdpPrompt(IN LPSTR PromptString,
     {
         _SEH2_TRY
         {
-            RtlMoveMemory(ResponseString, ResponseBuffer.Buffer, ResponseBuffer.Length);
+            /* Safely copy back response to user mode  */
+            KdpMoveMemory(ResponseString,
+                          ResponseBuffer.Buffer,
+                          ResponseBuffer.Length);
         }
         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
         {
+            /* String became invalid after we exited, fail  */
             _SEH2_YIELD(return 0);
         }
         _SEH2_END;
@@ -326,13 +347,21 @@ KdpPrint(IN ULONG ComponentId,
         /* Capture user-mode buffers */
         _SEH2_TRY
         {
-            ProbeForRead(String, Length, 1);
-            CapturedString = alloca(512);
-            RtlMoveMemory(CapturedString, String, Length);
+            /* Probe the string */
+            ProbeForRead(String,
+                         Length,
+                         1);
+
+            /* Capture it */
+            CapturedString = alloca(Length);
+            KdpMoveMemory(CapturedString,
+                          String,
+                          Length);
             String = CapturedString;
         }
         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
         {
+            /* Bad pointer, fail the print */
             _SEH2_YIELD(return STATUS_ACCESS_VIOLATION);
         }
         _SEH2_END;
index ce7e20c..91a83de 100644 (file)
@@ -58,13 +58,14 @@ KdpReport(IN PKTRAP_FRAME TrapFrame,
 {
     BOOLEAN Enable, Handled;
     PKPRCB Prcb;
-    NTSTATUS ExceptionCode = ExceptionRecord->ExceptionCode;
+    NTSTATUS ExceptionCode;
 
     /*
      * Determine whether to pass the exception to the debugger.
      * First, check if this is a "debug exception", meaning breakpoint
      * (including debug service), single step and assertion failure exceptions.
      */
+    ExceptionCode = ExceptionRecord->ExceptionCode;
     if ((ExceptionCode == STATUS_BREAKPOINT) ||
         (ExceptionCode == STATUS_SINGLE_STEP) ||
         (ExceptionCode == STATUS_ASSERTION_FAILURE))
@@ -92,8 +93,8 @@ KdpReport(IN PKTRAP_FRAME TrapFrame,
     else if (SecondChanceException == FALSE)
     {
         /*
-         * This isn't a debug exception and the stop-on-exception flag isn't
-         * set, so don't bother
+         * This isn't a debug exception and the stop-on-exception flag isn't set,
+         * so don't bother handling it
          */
         return FALSE;
     }
@@ -107,7 +108,7 @@ KdpReport(IN PKTRAP_FRAME TrapFrame,
      */
     Prcb = KeGetCurrentPrcb();
     KiSaveProcessorControlState(&Prcb->ProcessorState);
-    RtlCopyMemory(&Prcb->ProcessorState.ContextFrame,
+    KdpMoveMemory(&Prcb->ProcessorState.ContextFrame,
                   ContextRecord,
                   sizeof(CONTEXT));
 
@@ -118,7 +119,7 @@ KdpReport(IN PKTRAP_FRAME TrapFrame,
                                             SecondChanceException);
 
     /* Now restore the processor state, manually again. */
-    RtlCopyMemory(ContextRecord,
+    KdpMoveMemory(ContextRecord,
                   &Prcb->ProcessorState.ContextFrame,
                   sizeof(CONTEXT));
     KiRestoreProcessorControlState(&Prcb->ProcessorState);
@@ -138,7 +139,7 @@ KdpTrap(IN PKTRAP_FRAME TrapFrame,
         IN KPROCESSOR_MODE PreviousMode,
         IN BOOLEAN SecondChanceException)
 {
-    BOOLEAN Unload = FALSE;
+    BOOLEAN Unload;
     ULONG_PTR ProgramCounter;
     BOOLEAN Handled;
     NTSTATUS ReturnStatus;
@@ -156,6 +157,7 @@ KdpTrap(IN PKTRAP_FRAME TrapFrame,
         ProgramCounter = KeGetContextPc(ContextRecord);
 
         /* Check what kind of operation was requested from us */
+        Unload = FALSE;
         switch (ExceptionRecord->ExceptionInformation[0])
         {
             /* DbgPrint */
@@ -164,27 +166,24 @@ KdpTrap(IN PKTRAP_FRAME TrapFrame,
                 /* Call the worker routine */
                 ReturnStatus = KdpPrint((ULONG)KdpGetParameterThree(ContextRecord),
                                         (ULONG)KdpGetParameterFour(ContextRecord),
-                                        (LPSTR)ExceptionRecord->
-                                        ExceptionInformation[1],
-                                        (USHORT)ExceptionRecord->
-                                        ExceptionInformation[2],
+                                        (LPSTR)ExceptionRecord->ExceptionInformation[1],
+                                        (USHORT)ExceptionRecord->ExceptionInformation[2],
                                         PreviousMode,
                                         TrapFrame,
                                         ExceptionFrame,
                                         &Handled);
 
                 /* Update the return value for the caller */
-                KeSetContextReturnRegister(ContextRecord, ReturnStatus);
+                KeSetContextReturnRegister(ContextRecord,
+                                           ReturnStatus);
                 break;
 
             /* DbgPrompt */
             case BREAKPOINT_PROMPT:
 
                 /* Call the worker routine */
-                ReturnLength = KdpPrompt((LPSTR)ExceptionRecord->
-                                         ExceptionInformation[1],
-                                         (USHORT)ExceptionRecord->
-                                         ExceptionInformation[2],
+                ReturnLength = KdpPrompt((LPSTR)ExceptionRecord->ExceptionInformation[1],
+                                         (USHORT)ExceptionRecord->ExceptionInformation[2],
                                          (LPSTR)KdpGetParameterThree(ContextRecord),
                                          (USHORT)KdpGetParameterFour(ContextRecord),
                                          PreviousMode,
@@ -276,9 +275,10 @@ KdpStub(IN PKTRAP_FRAME TrapFrame,
         IN KPROCESSOR_MODE PreviousMode,
         IN BOOLEAN SecondChanceException)
 {
-    ULONG_PTR ExceptionCommand = ExceptionRecord->ExceptionInformation[0];
+    ULONG_PTR ExceptionCommand;
 
     /* Check if this was a breakpoint due to DbgPrint or Load/UnloadSymbols */
+    ExceptionCommand = ExceptionRecord->ExceptionInformation[0];
     if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
         (ExceptionRecord->NumberParameters > 0) &&
         ((ExceptionCommand == BREAKPOINT_LOAD_SYMBOLS) ||
index 4f6f11a..23de7c0 100644 (file)
@@ -44,6 +44,14 @@ MiInitializeSessionWsSupport(VOID)
     InitializeListHead(&MmWorkingSetExpansionHead);
 }
 
+BOOLEAN
+NTAPI
+MmIsSessionAddress(IN PVOID Address)
+{
+    /* Check if it is in range */
+    return MI_IS_SESSION_ADDRESS(Address) ? TRUE : FALSE;
+}
+
 LCID
 NTAPI
 MmGetSessionLocaleId(VOID)