https://git.reactos.org/?p=reactos.git;a=commitdiff;h=b3c55b9e6c9b0f62142f7…
commit b3c55b9e6c9b0f62142f7dbe3e3059f3f81c7f0d
Author:     Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Sun Mar 20 22:55:06 2022 +0100
Commit:     Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Wed May 17 17:40:37 2023 +0200
    [NTOS:LPC] Ensure debug-traced pointer-given user-mode data is captured. (#4399)
    CORE-18098
---
 ntoskrnl/lpc/connect.c | 64 ++++++++++++++++++++++++++++++++++----------------
 ntoskrnl/lpc/create.c  | 21 ++++++++++++-----
 ntoskrnl/lpc/send.c    | 27 +++++++++++----------
 3 files changed, 74 insertions(+), 38 deletions(-)
diff --git a/ntoskrnl/lpc/connect.c b/ntoskrnl/lpc/connect.c
index d1f2426ef73..69dff778ab4 100644
--- a/ntoskrnl/lpc/connect.c
+++ b/ntoskrnl/lpc/connect.c
@@ -90,6 +90,9 @@ NtSecureConnectPort(OUT PHANDLE PortHandle,
     NTSTATUS Status = STATUS_SUCCESS;
     KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
     PETHREAD Thread = PsGetCurrentThread();
+#if DBG
+    UNICODE_STRING CapturedPortName;
+#endif
     SECURITY_QUALITY_OF_SERVICE CapturedQos;
     PORT_VIEW CapturedClientView;
     PSID CapturedServerSid;
@@ -105,13 +108,6 @@ NtSecureConnectPort(OUT PHANDLE PortHandle,
     PTOKEN_USER TokenUserInfo;
     PAGED_CODE();
-    LPCTRACE(LPC_CONNECT_DEBUG,
-             "Name: %wZ. SecurityQos: %p. Views: %p/%p. Sid: %p\n",
-             PortName,
-             SecurityQos,
-             ClientView,
-             ServerView,
-             ServerSid);
     /* Check if the call comes from user mode */
     if (PreviousMode != KernelMode)
@@ -141,7 +137,6 @@ NtSecureConnectPort(OUT PHANDLE PortHandle,
                     /* Invalid size */
                     _SEH2_YIELD(return STATUS_INVALID_PARAMETER);
                 }
-
             }
             /* Capture the server view */
@@ -172,7 +167,7 @@ NtSecureConnectPort(OUT PHANDLE PortHandle,
                 ProbeForWrite(ConnectionInformation, ConnectionInfoLength,
sizeof(ULONG));
             CapturedServerSid = ServerSid;
-            if (ServerSid != NULL)
+            if (ServerSid)
             {
                 /* Capture it */
                 Status = SepCaptureSid(ServerSid,
@@ -231,6 +226,21 @@ NtSecureConnectPort(OUT PHANDLE PortHandle,
         CapturedServerSid = ServerSid;
     }
+#if DBG
+    /* Capture the port name for DPRINT only - ObReferenceObjectByName does
+     * its own capture. As it is used only for debugging, ignore any failure;
+     * the string is zeroed out in such case. */
+    ProbeAndCaptureUnicodeString(&CapturedPortName, PreviousMode, PortName);
+
+    LPCTRACE(LPC_CONNECT_DEBUG,
+             "Name: %wZ. SecurityQos: %p. Views: %p/%p. Sid: %p\n",
+             &CapturedPortName,
+             SecurityQos,
+             ClientView,
+             ServerView,
+             ServerSid);
+#endif
+
     /* Get the port */
     Status = ObReferenceObjectByName(PortName,
                                      0,
@@ -242,7 +252,10 @@ NtSecureConnectPort(OUT PHANDLE PortHandle,
                                      (PVOID*)&Port);
     if (!NT_SUCCESS(Status))
     {
-        DPRINT1("Failed to reference port '%wZ': 0x%lx\n", PortName,
Status);
+#if DBG
+        DPRINT1("Failed to reference port '%wZ': 0x%lx\n",
&CapturedPortName, Status);
+        ReleaseCapturedUnicodeString(&CapturedPortName, PreviousMode);
+#endif
         if (CapturedServerSid != ServerSid)
             SepReleaseSid(CapturedServerSid, PreviousMode, TRUE);
@@ -253,7 +266,10 @@ NtSecureConnectPort(OUT PHANDLE PortHandle,
     /* This has to be a connection port */
     if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_CONNECTION_PORT)
     {
-        DPRINT1("Port '%wZ' is not a connection port (Flags: 0x%lx)\n",
PortName, Port->Flags);
+#if DBG
+        DPRINT1("Port '%wZ' is not a connection port (Flags: 0x%lx)\n",
&CapturedPortName, Port->Flags);
+        ReleaseCapturedUnicodeString(&CapturedPortName, PreviousMode);
+#endif
         /* It isn't, so fail */
         ObDereferenceObject(Port);
@@ -282,7 +298,9 @@ NtSecureConnectPort(OUT PHANDLE PortHandle,
                 if (!RtlEqualSid(CapturedServerSid, TokenUserInfo->User.Sid))
                 {
                     /* Fail */
-                    DPRINT1("Port '%wZ': server SID mismatch\n",
PortName);
+#if DBG
+                    DPRINT1("Port '%wZ': server SID mismatch\n",
&CapturedPortName);
+#endif
                     Status = STATUS_SERVER_SID_MISMATCH;
                 }
@@ -293,21 +311,27 @@ NtSecureConnectPort(OUT PHANDLE PortHandle,
         else
         {
             /* Invalid SID */
-            DPRINT1("Port '%wZ': server SID mismatch\n", PortName);
+#if DBG
+            DPRINT1("Port '%wZ': server SID mismatch\n",
&CapturedPortName);
+#endif
             Status = STATUS_SERVER_SID_MISMATCH;
         }
         /* Finally release the captured SID, we don't need it anymore */
         if (CapturedServerSid != ServerSid)
             SepReleaseSid(CapturedServerSid, PreviousMode, TRUE);
+    }
-        /* Check if SID failed */
-        if (!NT_SUCCESS(Status))
-        {
-            /* Quit */
-            ObDereferenceObject(Port);
-            return Status;
-        }
+#if DBG
+    ReleaseCapturedUnicodeString(&CapturedPortName, PreviousMode);
+#endif
+
+    /* Check if SID failed */
+    if (ServerSid && !NT_SUCCESS(Status))
+    {
+        /* Quit */
+        ObDereferenceObject(Port);
+        return Status;
     }
     /* Create the client port */
diff --git a/ntoskrnl/lpc/create.c b/ntoskrnl/lpc/create.c
index aaa5ed70518..7c017b6b7e1 100644
--- a/ntoskrnl/lpc/create.c
+++ b/ntoskrnl/lpc/create.c
@@ -50,11 +50,13 @@ LpcpCreatePort(OUT PHANDLE PortHandle,
     NTSTATUS Status;
     KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
     UNICODE_STRING CapturedObjectName, *ObjectName;
+#if DBG
+    UNICODE_STRING CapturedPortName;
+#endif
     PLPCP_PORT_OBJECT Port;
     HANDLE Handle;
     PAGED_CODE();
-    LPCTRACE(LPC_CREATE_DEBUG, "Name: %wZ\n", ObjectAttributes->ObjectName);
     RtlInitEmptyUnicodeString(&CapturedObjectName, NULL, 0);
@@ -70,10 +72,7 @@ LpcpCreatePort(OUT PHANDLE PortHandle,
             ProbeForRead(ObjectAttributes, sizeof(*ObjectAttributes), sizeof(ULONG));
             ObjectName = ((volatile OBJECT_ATTRIBUTES*)ObjectAttributes)->ObjectName;
             if (ObjectName)
-            {
-                ProbeForRead(ObjectName, sizeof(*ObjectName), 1);
-                CapturedObjectName = *(volatile UNICODE_STRING*)ObjectName;
-            }
+                CapturedObjectName = ProbeForReadUnicodeString(ObjectName);
         }
         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
         {
@@ -88,10 +87,20 @@ LpcpCreatePort(OUT PHANDLE PortHandle,
             CapturedObjectName = *(ObjectAttributes->ObjectName);
     }
-    /* Normalize the buffer pointer in case we don't have a name */
+    /* Normalize the buffer pointer in case we don't have
+     * a name, for initializing an unconnected port. */
     if (CapturedObjectName.Length == 0)
         CapturedObjectName.Buffer = NULL;
+#if DBG
+    /* Capture the port name for DPRINT only - ObCreateObject does its
+     * own capture. As it is used only for debugging, ignore any failure;
+     * the string is zeroed out in such case. */
+    ProbeAndCaptureUnicodeString(&CapturedPortName, PreviousMode,
&CapturedObjectName);
+    LPCTRACE(LPC_CREATE_DEBUG, "Name: %wZ\n", &CapturedPortName);
+    ReleaseCapturedUnicodeString(&CapturedPortName, PreviousMode);
+#endif
+
     /* Create the Object */
     Status = ObCreateObject(PreviousMode,
                             LpcPortObjectType,
diff --git a/ntoskrnl/lpc/send.c b/ntoskrnl/lpc/send.c
index d6b22063014..317ad1e4563 100644
--- a/ntoskrnl/lpc/send.c
+++ b/ntoskrnl/lpc/send.c
@@ -449,11 +449,6 @@ NtRequestPort(IN HANDLE PortHandle,
     PLPCP_MESSAGE Message;
     PAGED_CODE();
-    LPCTRACE(LPC_SEND_DEBUG,
-             "Handle: %p. Message: %p. Type: %lx\n",
-             PortHandle,
-             LpcRequest,
-             LpcpGetMessageType(LpcRequest));
     /* Check if the call comes from user mode */
     if (PreviousMode != KernelMode)
@@ -476,6 +471,12 @@ NtRequestPort(IN HANDLE PortHandle,
         CapturedLpcRequest = *LpcRequest;
     }
+    LPCTRACE(LPC_SEND_DEBUG,
+             "Handle: %p. Message: %p. Type: %lx\n",
+             PortHandle,
+             LpcRequest,
+             LpcpGetMessageType(&CapturedLpcRequest));
+
     /* Get the message type */
     MessageType = CapturedLpcRequest.u2.s2.Type | LPC_DATAGRAM;
@@ -709,15 +710,10 @@ NtRequestWaitReplyPort(IN HANDLE PortHandle,
     PLPCP_DATA_INFO DataInfo;
     PAGED_CODE();
-    LPCTRACE(LPC_SEND_DEBUG,
-             "Handle: %p. Messages: %p/%p. Type: %lx\n",
-             PortHandle,
-             LpcRequest,
-             LpcReply,
-             LpcpGetMessageType(LpcRequest));
     /* Check if the thread is dying */
-    if (Thread->LpcExitThreadCalled) return STATUS_THREAD_IS_TERMINATING;
+    if (Thread->LpcExitThreadCalled)
+        return STATUS_THREAD_IS_TERMINATING;
     /* Check for user mode access */
     if (PreviousMode != KernelMode)
@@ -757,6 +753,13 @@ NtRequestWaitReplyPort(IN HANDLE PortHandle,
         }
     }
+    LPCTRACE(LPC_SEND_DEBUG,
+             "Handle: %p. Messages: %p/%p. Type: %lx\n",
+             PortHandle,
+             LpcRequest,
+             LpcReply,
+             LpcpGetMessageType(&CapturedLpcRequest));
+
     /* This flag is undocumented. Remove it before continuing */
     CapturedLpcRequest.u2.s2.Type &= ~0x4000;