https://git.reactos.org/?p=reactos.git;a=commitdiff;h=1a38c76266b30b9895563…
commit 1a38c76266b30b9895563b57d398beac108fd729
Author: Thomas Faber <thomas.faber(a)reactos.org>
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;
}