https://git.reactos.org/?p=reactos.git;a=commitdiff;h=1a38c76266b30b9895563b57d398beac108fd729

commit 1a38c76266b30b9895563b57d398beac108fd729
Author: Thomas Faber <[email protected]>
AuthorDate: Fri Dec 8 14:39:31 2017 +0100

    [NTOS:KD] Protect against invalid user arguments in KdpPrompt. CORE-14057
---
 ntoskrnl/include/internal/kd.h |  9 +++---
 ntoskrnl/kd/kdmain.c           |  3 +-
 ntoskrnl/kdbg/kdb_cli.c        | 72 +++++++++++++++++++++++++++++++++++++++---
 3 files changed, 75 insertions(+), 9 deletions(-)

diff --git a/ntoskrnl/include/internal/kd.h b/ntoskrnl/include/internal/kd.h
index d3daabfeb7..9bb744319a 100644
--- a/ntoskrnl/include/internal/kd.h
+++ b/ntoskrnl/include/internal/kd.h
@@ -199,10 +199,11 @@ KdpPrintString(
 ULONG
 NTAPI
 KdpPrompt(
-    IN LPSTR InString,
-    IN USHORT InStringLength,
-    OUT LPSTR OutString,
-    IN USHORT OutStringLength
+    _In_reads_bytes_(InStringLength) PCHAR UnsafeInString,
+    _In_ USHORT InStringLength,
+    _Out_writes_bytes_(OutStringLength) PCHAR UnsafeOutString,
+    _In_ USHORT OutStringLength,
+    _In_ KPROCESSOR_MODE PreviousMode
 );
 
 BOOLEAN
diff --git a/ntoskrnl/kd/kdmain.c b/ntoskrnl/kd/kdmain.c
index aca1961bb0..a6627b8ec0 100644
--- a/ntoskrnl/kd/kdmain.c
+++ b/ntoskrnl/kd/kdmain.c
@@ -175,7 +175,8 @@ KdpEnterDebuggerException(IN PKTRAP_FRAME TrapFrame,
                                     (USHORT)ExceptionRecord->
                                     ExceptionInformation[2],
                                     OutString,
-                                    OutStringLength);
+                                    OutStringLength,
+                                    PreviousMode);
 
             /* Return the number of characters that we received */
             Context->Eax = ReturnValue;
diff --git a/ntoskrnl/kdbg/kdb_cli.c b/ntoskrnl/kdbg/kdb_cli.c
index d5e7fde4d2..db7dae7981 100644
--- a/ntoskrnl/kdbg/kdb_cli.c
+++ b/ntoskrnl/kdbg/kdb_cli.c
@@ -3662,15 +3662,61 @@ extern KSPIN_LOCK KdpSerialSpinLock;
 
 ULONG
 NTAPI
-KdpPrompt(IN LPSTR InString,
-          IN USHORT InStringLength,
-          OUT LPSTR OutString,
-          IN USHORT OutStringLength)
+KdpPrompt(
+    _In_reads_bytes_(InStringLength) PCHAR UnsafeInString,
+    _In_ USHORT InStringLength,
+    _Out_writes_bytes_(OutStringLength) PCHAR UnsafeOutString,
+    _In_ USHORT OutStringLength,
+    _In_ KPROCESSOR_MODE PreviousMode)
 {
     USHORT i;
     CHAR Response;
     ULONG DummyScanCode;
     KIRQL OldIrql;
+    PCHAR InString;
+    PCHAR OutString;
+
+    /* Normalize the lengths */
+    InStringLength = min(InStringLength,
+                         512);
+    OutStringLength = min(OutStringLength,
+                          512);
+
+    /* Check if we need to verify the string */
+    if (PreviousMode != KernelMode)
+    {
+        /* Handle user-mode buffers safely */
+        _SEH2_TRY
+        {
+            /* Probe the prompt */
+            ProbeForRead(UnsafeInString,
+                         InStringLength,
+                         1);
+
+            /* Capture prompt */
+            InString = _alloca(InStringLength);
+            RtlCopyMemory(InString,
+                          UnsafeInString,
+                          InStringLength);
+
+            /* Probe and make room for response */
+            ProbeForWrite(UnsafeOutString,
+                          OutStringLength,
+                          1);
+            OutString = _alloca(OutStringLength);
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            /* Bad string pointer, bail out */
+            _SEH2_YIELD(return 0);
+        }
+        _SEH2_END;
+    }
+    else
+    {
+        InString = UnsafeInString;
+        OutString = UnsafeOutString;
+    }
 
     /* Acquire the printing spinlock without waiting at raised IRQL */
     while (TRUE)
@@ -3779,6 +3825,24 @@ KdpPrompt(IN LPSTR InString,
     /* Lower IRQL back */
     KeLowerIrql(OldIrql);
 
+    /* Copy back response if required */
+    if (PreviousMode != KernelMode)
+    {
+        _SEH2_TRY
+        {
+            /* Safely copy back response to user mode */
+            RtlCopyMemory(UnsafeOutString,
+                          OutString,
+                          i);
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            /* String became invalid after we exited, fail */
+            _SEH2_YIELD(return 0);
+        }
+        _SEH2_END;
+    }
+
     /* Return the length  */
     return i;
 }

Reply via email to