[NTOS] Fixes for NtDisplayString().
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Thu, 20 Dec 2018 02:32:08 +0000 (03:32 +0100)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Thu, 20 Dec 2018 02:47:36 +0000 (03:47 +0100)
- Require the user to have TCB privilege for using this function.
- Probe and capture the user-provided string (and avoid usermode-triggered BSODS ;-)
- Allocate the OEM-converted string in *NonPagedPool* because we are
  going to transmit the buffer to BOOTVID.

ntoskrnl/inbv/inbv.c

index cb6af3e..75825d0 100644 (file)
@@ -5,6 +5,10 @@
 #include <debug.h>
 #include "bootvid/bootvid.h"
 
+#ifndef TAG_OSTR
+#define TAG_OSTR    'RTSO'
+#endif
+
 /* GLOBALS *******************************************************************/
 
 /*
@@ -771,15 +775,62 @@ NTSTATUS
 NTAPI
 NtDisplayString(IN PUNICODE_STRING DisplayString)
 {
+    NTSTATUS Status;
+    UNICODE_STRING CapturedString;
     OEM_STRING OemString;
+    KPROCESSOR_MODE PreviousMode;
+
+    PAGED_CODE();
+
+    PreviousMode = ExGetPreviousMode();
+
+    /* We require the TCB privilege */
+    if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
+        return STATUS_PRIVILEGE_NOT_HELD;
+
+    /* Capture the string */
+    Status = ProbeAndCaptureUnicodeString(&CapturedString, PreviousMode, DisplayString);
+    if (!NT_SUCCESS(Status))
+        return Status;
+
+    /* Do not display the string if it is empty */
+    if (CapturedString.Length == 0 || CapturedString.Buffer == NULL)
+    {
+        Status = STATUS_SUCCESS;
+        goto Quit;
+    }
 
-    /* Convert the string to OEM and display it */
-    RtlUnicodeStringToOemString(&OemString, DisplayString, TRUE);
+    /*
+     * Convert the string since INBV understands only ANSI/OEM. Allocate the
+     * string buffer in non-paged pool because INBV passes it down to BOOTVID.
+     * We cannot perform the allocation using RtlUnicodeStringToOemString()
+     * since its allocator uses PagedPool.
+     */
+    RtlInitEmptyAnsiString((PANSI_STRING)&OemString, NULL,
+                           RtlUnicodeStringToOemSize(&CapturedString));
+    OemString.Buffer = ExAllocatePoolWithTag(NonPagedPool,
+                                             OemString.MaximumLength,
+                                             TAG_OSTR);
+    if (OemString.Buffer == NULL)
+    {
+        Status = STATUS_NO_MEMORY;
+        goto Quit;
+    }
+    RtlUnicodeStringToOemString(&OemString, &CapturedString, FALSE);
+
+    /* Display the string */
     InbvDisplayString(OemString.Buffer);
-    RtlFreeOemString(&OemString);
 
-    /* Return success */
-    return STATUS_SUCCESS;
+    /* Free the string buffer */
+    ExFreePoolWithTag(OemString.Buffer, TAG_OSTR);
+
+    Status = STATUS_SUCCESS;
+
+Quit:
+    /* Free the captured string */
+    ReleaseCapturedUnicodeString(&CapturedString, PreviousMode);
+
+    return Status;
 }
 
 #ifdef INBV_ROTBAR_IMPLEMENTED