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