From ce1a5160ecbce4af509718142561d1b598ea3da3 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Sun, 25 May 2014 10:21:08 +0000 Subject: [PATCH 1/1] [NTOSKRNL] 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 | 134 ++++++++++++++++++++++++++------ reactos/ntoskrnl/lpc/create.c | 55 ++++++++++++- 2 files changed, 161 insertions(+), 28 deletions(-) diff --git a/reactos/ntoskrnl/lpc/complete.c b/reactos/ntoskrnl/lpc/complete.c index 5134757f269..0f9f7f27682 100644 --- a/reactos/ntoskrnl/lpc/complete.c +++ b/reactos/ntoskrnl/lpc/complete.c @@ -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, diff --git a/reactos/ntoskrnl/lpc/create.c b/reactos/ntoskrnl/lpc/create.c index b4fb88589e9..10ab79023b9 100644 --- a/reactos/ntoskrnl/lpc/create.c +++ b/reactos/ntoskrnl/lpc/create.c @@ -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; } -- 2.17.1