[NTOSKRNL]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Sun, 25 May 2014 10:21:08 +0000 (10:21 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Sun, 25 May 2014 10:21:08 +0000 (10:21 +0000)
Add SEH to LpcpCreatePort and NtAcceptConnectPort. Based on patches by Aleksander Andrejevic ([TheFlash])
CORE-7156 #resolve
CORE-7371 #comment SEH still missing in NtSecureConnectPort, NtReplyPort, NtReplyWaitReceivePortEx, NtRequestPort

svn path=/trunk/; revision=63436

reactos/ntoskrnl/lpc/complete.c
reactos/ntoskrnl/lpc/create.c

index 5134757..0f9f7f2 100644 (file)
@@ -55,6 +55,8 @@ NtAcceptConnectPort(OUT PHANDLE PortHandle,
     PEPROCESS ClientProcess;
     PETHREAD ClientThread;
     LARGE_INTEGER SectionOffset;
+    CLIENT_ID ClientId;
+    ULONG MessageId;
     PAGED_CODE();
     LPCTRACE(LPC_COMPLETE_DEBUG,
              "Context: %p. Message: %p. Accept: %lx. Views: %p/%p\n",
@@ -64,22 +66,81 @@ NtAcceptConnectPort(OUT PHANDLE PortHandle,
              ClientView,
              ServerView);
 
-    /* Validate the size of the server view */
-    if ((ServerView) && (ServerView->Length != sizeof(PORT_VIEW)))
+    /* Check if the call comes from user mode */
+    if (PreviousMode != KernelMode)
     {
-        /* Invalid size */
-        return STATUS_INVALID_PARAMETER;
+        /* Enter SEH for probing the parameters */
+        _SEH2_TRY
+        {
+            ProbeForWriteHandle(PortHandle);
+
+            /* Probe the basic ReplyMessage structure */
+            ProbeForRead(ReplyMessage, sizeof(PORT_MESSAGE), sizeof(ULONG));
+
+            /* Grab some values */
+            ClientId = ReplyMessage->ClientId;
+            MessageId = ReplyMessage->MessageId;
+            ConnectionInfoLength = ReplyMessage->u1.s1.DataLength;
+
+            /* Probe the connection info */
+            ProbeForRead(ReplyMessage + 1, ConnectionInfoLength, 1);
+
+            /* The following parameters are optional */
+            if (ServerView != NULL)
+            {
+                ProbeForWrite(ServerView, sizeof(PORT_VIEW), sizeof(ULONG));
+
+                /* Validate the size of the server view */
+                if (ServerView->Length != sizeof(PORT_VIEW))
+                {
+                    /* Invalid size */
+                    _SEH2_YIELD(return STATUS_INVALID_PARAMETER);
+                }
+            }
+
+            if (ClientView != NULL)
+            {
+                ProbeForWrite(ClientView, sizeof(REMOTE_PORT_VIEW), sizeof(ULONG));
+
+                /* Validate the size of the client view */
+                if (ClientView->Length != sizeof(REMOTE_PORT_VIEW))
+                {
+                    /* Invalid size */
+                    _SEH2_YIELD(return STATUS_INVALID_PARAMETER);
+                }
+            }
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            /* There was an exception, return the exception code */
+            _SEH2_YIELD(return _SEH2_GetExceptionCode());
+        }
+        _SEH2_END;
     }
-
-    /* Validate the size of the client view */
-    if ((ClientView) && (ClientView->Length != sizeof(REMOTE_PORT_VIEW)))
+    else
     {
-        /* Invalid size */
-        return STATUS_INVALID_PARAMETER;
+        /* Grab some values */
+        ClientId = ReplyMessage->ClientId;
+        MessageId = ReplyMessage->MessageId;
+        ConnectionInfoLength = ReplyMessage->u1.s1.DataLength;
+
+        /* Validate the size of the server view */
+        if ((ServerView) && (ServerView->Length != sizeof(PORT_VIEW)))
+        {
+            /* Invalid size */
+            return STATUS_INVALID_PARAMETER;
+        }
+
+        /* Validate the size of the client view */
+        if ((ClientView) && (ClientView->Length != sizeof(REMOTE_PORT_VIEW)))
+        {
+            /* Invalid size */
+            return STATUS_INVALID_PARAMETER;
+        }
     }
 
     /* Get the client process and thread */
-    Status = PsLookupProcessThreadByCid(&ReplyMessage->ClientId,
+    Status = PsLookupProcessThreadByCid(&ClientId,
                                         &ClientProcess,
                                         &ClientThread);
     if (!NT_SUCCESS(Status)) return Status;
@@ -89,8 +150,8 @@ NtAcceptConnectPort(OUT PHANDLE PortHandle,
 
     /* Make sure that the client wants a reply, and this is the right one */
     if (!(LpcpGetMessageFromThread(ClientThread)) ||
-        !(ReplyMessage->MessageId) ||
-        (ClientThread->LpcReplyMessageId != ReplyMessage->MessageId))
+        !(MessageId) ||
+        (ClientThread->LpcReplyMessageId != MessageId))
     {
         /* Not the reply asked for, or no reply wanted, fail */
         KeReleaseGuardedMutex(&LpcpLock);
@@ -125,8 +186,7 @@ NtAcceptConnectPort(OUT PHANDLE PortHandle,
     ConnectMessage->ClientPort = NULL;
     KeReleaseGuardedMutex(&LpcpLock);
 
-    /* Get the connection information length */
-    ConnectionInfoLength = ReplyMessage->u1.s1.DataLength;
+    /* Check the connection information length */
     if (ConnectionInfoLength > ConnectionPort->MaxConnectionInfoLength)
     {
         /* Normalize it since it's too large */
@@ -142,16 +202,26 @@ NtAcceptConnectPort(OUT PHANDLE PortHandle,
     /* Setup the reply message */
     Message->Request.u2.s2.Type = LPC_REPLY;
     Message->Request.u2.s2.DataInfoOffset = 0;
-    Message->Request.ClientId = ReplyMessage->ClientId;
-    Message->Request.MessageId = ReplyMessage->MessageId;
+    Message->Request.ClientId = ClientId;
+    Message->Request.MessageId = MessageId;
     Message->Request.ClientViewSize = 0;
-    RtlCopyMemory(ConnectMessage + 1, ReplyMessage + 1, ConnectionInfoLength);
+
+    _SEH2_TRY
+    {
+        RtlCopyMemory(ConnectMessage + 1, ReplyMessage + 1, ConnectionInfoLength);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = _SEH2_GetExceptionCode();
+        _SEH2_YIELD(goto Cleanup);
+    }
+    _SEH2_END;
 
     /* At this point, if the caller refused the connection, go to cleanup */
     if (!AcceptConnection)
     {
         DPRINT1("LPC connection was refused\n");
-        goto Cleanup;   
+        goto Cleanup;
     }
 
     /* Otherwise, create the actual port */
@@ -259,16 +329,30 @@ NtAcceptConnectPort(OUT PHANDLE PortHandle,
         goto Cleanup;
     }
 
-    /* Check if the caller gave a client view */
-    if (ClientView)
+    /* Enter SEH to write back the results */
+    _SEH2_TRY
     {
-        /* Fill it out */
-        ClientView->ViewBase = ConnectMessage->ClientView.ViewRemoteBase;
-        ClientView->ViewSize = ConnectMessage->ClientView.ViewSize;
+        /* Check if the caller gave a client view */
+        if (ClientView)
+        {
+            /* Fill it out */
+            ClientView->ViewBase = ConnectMessage->ClientView.ViewRemoteBase;
+            ClientView->ViewSize = ConnectMessage->ClientView.ViewSize;
+        }
+
+        /* Return the handle to user mode */
+        *PortHandle = Handle;
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        /* Cleanup and return the exception code */
+        ObCloseHandle(Handle, UserMode);
+        ObDereferenceObject(ServerPort);
+        Status = _SEH2_GetExceptionCode();
+        _SEH2_YIELD(goto Cleanup);
     }
+    _SEH2_END;
 
-    /* Return the handle to user mode */
-    *PortHandle = Handle;
     LPCTRACE(LPC_COMPLETE_DEBUG,
              "Handle: %p. Messages: %p/%p. Ports: %p/%p/%p\n",
              Handle,
index b4fb885..10ab790 100644 (file)
@@ -49,9 +49,44 @@ LpcpCreatePort(OUT PHANDLE PortHandle,
     KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
     NTSTATUS Status;
     PLPCP_PORT_OBJECT Port;
+    HANDLE Handle;
+    PUNICODE_STRING ObjectName;
+    BOOLEAN NoName;
     PAGED_CODE();
     LPCTRACE(LPC_CREATE_DEBUG, "Name: %wZ\n", ObjectAttributes->ObjectName);
 
+    /* Check if the call comes from user mode */
+    if (PreviousMode != KernelMode)
+    {
+        _SEH2_TRY
+        {
+            /* Probe the PortHandle */
+            ProbeForWriteHandle(PortHandle);
+
+            /* Probe the ObjectAttributes */
+            ProbeForRead(ObjectAttributes, sizeof(OBJECT_ATTRIBUTES), sizeof(ULONG));
+
+            /* Get the object name and probe the unicode string */
+            ObjectName = ObjectAttributes->ObjectName;
+            ProbeForRead(ObjectName, sizeof(UNICODE_STRING), 1);
+
+            /* Check if we have no name */
+            NoName = (ObjectName->Buffer == NULL) || (ObjectName->Length == 0);
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            /* Return the exception code */
+            _SEH2_YIELD(return _SEH2_GetExceptionCode());
+        }
+        _SEH2_END;
+    }
+    else
+    {
+        /* Check if we have no name */
+        NoName = (ObjectAttributes->ObjectName->Buffer == NULL) ||
+                 (ObjectAttributes->ObjectName->Length == 0);
+    }
+
     /* Create the Object */
     Status = ObCreateObject(PreviousMode,
                             LpcPortObjectType,
@@ -72,7 +107,7 @@ LpcpCreatePort(OUT PHANDLE PortHandle,
     InitializeListHead(&Port->LpcReplyChainHead);
 
     /* Check if we don't have a name */
-    if (!ObjectAttributes->ObjectName->Buffer)
+    if (NoName)
     {
         /* Set up for an unconnected port */
         Port->Flags = LPCP_UNCONNECTED_PORT;
@@ -140,10 +175,24 @@ LpcpCreatePort(OUT PHANDLE PortHandle,
                             PORT_ALL_ACCESS,
                             0,
                             NULL,
-                            PortHandle);
+                            &Handle);
+    if (NT_SUCCESS(Status))
+    {
+        _SEH2_TRY
+        {
+            /* Write back the handle, pointer was already probed */
+            *PortHandle = Handle;
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            ObCloseHandle(Handle, UserMode);
+            Status = _SEH2_GetExceptionCode();
+        }
+        _SEH2_END;
+    }
 
     /* Return success or the error */
-    LPCTRACE(LPC_CREATE_DEBUG, "Port: %p. Handle: %p\n", Port, *PortHandle);
+    LPCTRACE(LPC_CREATE_DEBUG, "Port: %p. Handle: %p\n", Port, Handle);
     return Status;
 }