Index: ntoskrnl/lpc/close.c =================================================================== --- ntoskrnl/lpc/close.c (révision 73151) +++ ntoskrnl/lpc/close.c (copie de travail) @@ -116,6 +116,8 @@ PLPCP_MESSAGE Message; PLPCP_PORT_OBJECT ConnectionPort = NULL; PLPCP_CONNECTION_MESSAGE ConnectMessage; + PLPCP_NONPAGED_PORT_QUEUE MessageQueue; + PAGED_CODE(); LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p. Flags: %lx\n", Port, Port->Flags); @@ -229,9 +231,10 @@ if (Port->MsgQueue.Semaphore) { /* Use the semaphore to find the port queue and free it */ - ExFreePool(CONTAINING_RECORD(Port->MsgQueue.Semaphore, - LPCP_NONPAGED_PORT_QUEUE, - Semaphore)); + MessageQueue = CONTAINING_RECORD(Port->MsgQueue.Semaphore, + LPCP_NONPAGED_PORT_QUEUE, + Semaphore); + ExFreePoolWithTag(MessageQueue, 'troP'); } } } @@ -245,6 +248,7 @@ IN ULONG SystemHandleCount) { PLPCP_PORT_OBJECT Port = (PLPCP_PORT_OBJECT)Object; + LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p. Flags: %lx\n", Port, Port->Flags); /* Only Server-side Connection Ports need clean up*/ @@ -306,6 +310,7 @@ HANDLE Pid; CLIENT_DIED_MSG ClientDiedMsg; Timeout.QuadPart = -1000000; + PAGED_CODE(); LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p. Flags: %lx\n", Port, Port->Flags); @@ -347,8 +352,8 @@ for (;;) { /* Send the message */ - if (LpcRequestPort(Port, - &ClientDiedMsg.h) != STATUS_NO_MEMORY) break; + if (LpcRequestPort(Port, &ClientDiedMsg.h) != STATUS_NO_MEMORY) + break; /* Wait until trying again */ KeDelayExecutionThread(KernelMode, FALSE, &Timeout); Index: ntoskrnl/lpc/complete.c =================================================================== --- ntoskrnl/lpc/complete.c (révision 73151) +++ ntoskrnl/lpc/complete.c (copie de travail) @@ -41,22 +41,23 @@ IN PVOID PortContext OPTIONAL, IN PPORT_MESSAGE ReplyMessage, IN BOOLEAN AcceptConnection, - IN PPORT_VIEW ServerView, - IN PREMOTE_PORT_VIEW ClientView) + IN OUT PPORT_VIEW ServerView OPTIONAL, + OUT PREMOTE_PORT_VIEW ClientView OPTIONAL) { + NTSTATUS Status; + KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); + PORT_VIEW CapturedServerView; + PORT_MESSAGE CapturedReplyMessage; + ULONG ConnectionInfoLength; PLPCP_PORT_OBJECT ConnectionPort, ServerPort, ClientPort; + PLPCP_CONNECTION_MESSAGE ConnectMessage; + PLPCP_MESSAGE Message; PVOID ClientSectionToMap = NULL; HANDLE Handle; - KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); - NTSTATUS Status; - ULONG ConnectionInfoLength; - PLPCP_MESSAGE Message; - PLPCP_CONNECTION_MESSAGE ConnectMessage; 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", @@ -69,19 +70,16 @@ /* Check if the call comes from user mode */ if (PreviousMode != KernelMode) { - /* Enter SEH for probing the parameters */ _SEH2_TRY { + /* Probe the PortHandle */ ProbeForWriteHandle(PortHandle); /* Probe the basic ReplyMessage structure */ - ProbeForRead(ReplyMessage, sizeof(PORT_MESSAGE), sizeof(ULONG)); + ProbeForRead(ReplyMessage, sizeof(*ReplyMessage), sizeof(ULONG)); + CapturedReplyMessage = *(volatile PORT_MESSAGE*)ReplyMessage; + ConnectionInfoLength = CapturedReplyMessage.u1.s1.DataLength; - /* Grab some values */ - ClientId = ReplyMessage->ClientId; - MessageId = ReplyMessage->MessageId; - ConnectionInfoLength = ReplyMessage->u1.s1.DataLength; - /* Probe the connection info */ ProbeForRead(ReplyMessage + 1, ConnectionInfoLength, 1); @@ -88,10 +86,11 @@ /* The following parameters are optional */ if (ServerView != NULL) { - ProbeForWrite(ServerView, sizeof(PORT_VIEW), sizeof(ULONG)); + ProbeForWrite(ServerView, sizeof(*ServerView), sizeof(ULONG)); + CapturedServerView = *(volatile PORT_VIEW*)ServerView; /* Validate the size of the server view */ - if (ServerView->Length != sizeof(PORT_VIEW)) + if (CapturedServerView.Length != sizeof(CapturedServerView)) { /* Invalid size */ _SEH2_YIELD(return STATUS_INVALID_PARAMETER); @@ -100,10 +99,10 @@ if (ClientView != NULL) { - ProbeForWrite(ClientView, sizeof(REMOTE_PORT_VIEW), sizeof(ULONG)); + ProbeForWrite(ClientView, sizeof(*ClientView), sizeof(ULONG)); /* Validate the size of the client view */ - if (ClientView->Length != sizeof(REMOTE_PORT_VIEW)) + if (((volatile REMOTE_PORT_VIEW*)ClientView)->Length != sizeof(*ClientView)) { /* Invalid size */ _SEH2_YIELD(return STATUS_INVALID_PARAMETER); @@ -119,20 +118,19 @@ } else { - /* Grab some values */ - ClientId = ReplyMessage->ClientId; - MessageId = ReplyMessage->MessageId; - ConnectionInfoLength = ReplyMessage->u1.s1.DataLength; + CapturedReplyMessage = *ReplyMessage; + ConnectionInfoLength = CapturedReplyMessage.u1.s1.DataLength; /* Validate the size of the server view */ - if ((ServerView) && (ServerView->Length != sizeof(PORT_VIEW))) + if ((ServerView) && (ServerView->Length != sizeof(*ServerView))) { /* Invalid size */ return STATUS_INVALID_PARAMETER; } + CapturedServerView = *ServerView; /* Validate the size of the client view */ - if ((ClientView) && (ClientView->Length != sizeof(REMOTE_PORT_VIEW))) + if ((ClientView) && (ClientView->Length != sizeof(*ClientView))) { /* Invalid size */ return STATUS_INVALID_PARAMETER; @@ -140,7 +138,7 @@ } /* Get the client process and thread */ - Status = PsLookupProcessThreadByCid(&ClientId, + Status = PsLookupProcessThreadByCid(&CapturedReplyMessage.ClientId, &ClientProcess, &ClientThread); if (!NT_SUCCESS(Status)) return Status; @@ -150,8 +148,8 @@ /* Make sure that the client wants a reply, and this is the right one */ if (!(LpcpGetMessageFromThread(ClientThread)) || - !(MessageId) || - (ClientThread->LpcReplyMessageId != MessageId)) + !(CapturedReplyMessage.MessageId) || + (ClientThread->LpcReplyMessageId != CapturedReplyMessage.MessageId)) { /* Not the reply asked for, or no reply wanted, fail */ KeReleaseGuardedMutex(&LpcpLock); @@ -202,8 +200,8 @@ /* Setup the reply message */ Message->Request.u2.s2.Type = LPC_REPLY; Message->Request.u2.s2.DataInfoOffset = 0; - Message->Request.ClientId = ClientId; - Message->Request.MessageId = MessageId; + Message->Request.ClientId = CapturedReplyMessage.ClientId; + Message->Request.MessageId = CapturedReplyMessage.MessageId; Message->Request.ClientViewSize = 0; _SEH2_TRY @@ -309,6 +307,7 @@ if (ServerView) { /* FIXME: TODO */ + UNREFERENCED_PARAMETER(CapturedServerView); ASSERT(FALSE); } @@ -346,7 +345,7 @@ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Cleanup and return the exception code */ - ObCloseHandle(Handle, UserMode); + ObCloseHandle(Handle, PreviousMode); ObDereferenceObject(ServerPort); Status = _SEH2_GetExceptionCode(); _SEH2_YIELD(goto Cleanup); @@ -407,9 +406,10 @@ NtCompleteConnectPort(IN HANDLE PortHandle) { NTSTATUS Status; + KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); PLPCP_PORT_OBJECT Port; - KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); PETHREAD Thread; + PAGED_CODE(); LPCTRACE(LPC_COMPLETE_DEBUG, "Handle: %p\n", PortHandle); @@ -462,7 +462,7 @@ KeReleaseGuardedMutex(&LpcpLock); LpcpCompleteWait(&Thread->LpcReplySemaphore); - /* Dereference the Thread and Port and return */ + /* Dereference the Thread and Port and return */ ObDereferenceObject(Port); ObDereferenceObject(Thread); LPCTRACE(LPC_COMPLETE_DEBUG, "Port: %p. Thread: %p\n", Port, Thread); Index: ntoskrnl/lpc/connect.c =================================================================== --- ntoskrnl/lpc/connect.c (révision 73151) +++ ntoskrnl/lpc/connect.c (copie de travail) @@ -79,7 +79,7 @@ NTAPI NtSecureConnectPort(OUT PHANDLE PortHandle, IN PUNICODE_STRING PortName, - IN PSECURITY_QUALITY_OF_SERVICE Qos, + IN PSECURITY_QUALITY_OF_SERVICE SecurityQos, IN OUT PPORT_VIEW ClientView OPTIONAL, IN PSID ServerSid OPTIONAL, IN OUT PREMOTE_PORT_VIEW ServerView OPTIONAL, @@ -87,47 +87,148 @@ IN OUT PVOID ConnectionInformation OPTIONAL, IN OUT PULONG ConnectionInformationLength OPTIONAL) { + NTSTATUS Status = STATUS_SUCCESS; + KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); + PETHREAD Thread = PsGetCurrentThread(); + SECURITY_QUALITY_OF_SERVICE CapturedQos; + PORT_VIEW CapturedClientView; + PSID CapturedServerSid; ULONG ConnectionInfoLength = 0; PLPCP_PORT_OBJECT Port, ClientPort; - KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); - NTSTATUS Status = STATUS_SUCCESS; - HANDLE Handle; - PVOID SectionToMap; PLPCP_MESSAGE Message; PLPCP_CONNECTION_MESSAGE ConnectMessage; - PETHREAD Thread = PsGetCurrentThread(); ULONG PortMessageLength; + HANDLE Handle; + PVOID SectionToMap; LARGE_INTEGER SectionOffset; PTOKEN Token; PTOKEN_USER TokenUserInfo; + PAGED_CODE(); LPCTRACE(LPC_CONNECT_DEBUG, - "Name: %wZ. Qos: %p. Views: %p/%p. Sid: %p\n", + "Name: %wZ. SecurityQos: %p. Views: %p/%p. Sid: %p\n", PortName, - Qos, + SecurityQos, ClientView, ServerView, ServerSid); - /* Validate client view */ - if ((ClientView) && (ClientView->Length != sizeof(PORT_VIEW))) + /* Check if the call comes from user mode */ + if (PreviousMode != KernelMode) { - /* Fail */ - return STATUS_INVALID_PARAMETER; + /* Enter SEH for probing the parameters */ + _SEH2_TRY + { + /* Probe the PortHandle */ + ProbeForWriteHandle(PortHandle); + + /* Probe and capture the QoS */ + ProbeForRead(SecurityQos, sizeof(*SecurityQos), sizeof(ULONG)); + CapturedQos = *(volatile SECURITY_QUALITY_OF_SERVICE*)SecurityQos; + /* NOTE: Do not care about CapturedQos.Length */ + + /* The following parameters are optional */ + + /* Capture the client view */ + if (ClientView != NULL) + { + ProbeForWrite(ClientView, sizeof(*ClientView), sizeof(ULONG)); + CapturedClientView = *(volatile PORT_VIEW*)ClientView; + + /* Validate the size of the client view */ + if (CapturedClientView.Length != sizeof(CapturedClientView)) + { + /* Invalid size */ + _SEH2_YIELD(return STATUS_INVALID_PARAMETER); + } + + } + + /* Capture the server view */ + if (ServerView != NULL) + { + ProbeForWrite(ServerView, sizeof(*ServerView), sizeof(ULONG)); + + /* Validate the size of the server view */ + if (((volatile REMOTE_PORT_VIEW*)ServerView)->Length != sizeof(*ServerView)) + { + /* Invalid size */ + _SEH2_YIELD(return STATUS_INVALID_PARAMETER); + } + } + + if (MaxMessageLength) + ProbeForWriteUlong(MaxMessageLength); + + /* Capture connection information length */ + if (ConnectionInformationLength) + { + ProbeForWriteUlong(ConnectionInformationLength); + ConnectionInfoLength = *(volatile ULONG*)ConnectionInformationLength; + } + + /* Probe the ConnectionInformation */ + if (ConnectionInformation) + ProbeForWrite(ConnectionInformation, ConnectionInfoLength, sizeof(ULONG)); + + CapturedServerSid = ServerSid; + if (ServerSid != NULL) + { + /* Capture it */ + Status = SepCaptureSid(ServerSid, + PreviousMode, + PagedPool, + TRUE, + &CapturedServerSid); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to capture ServerSid!\n"); + _SEH2_YIELD(return Status); + } + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* There was an exception, return the exception code */ + _SEH2_YIELD(return _SEH2_GetExceptionCode()); + } + _SEH2_END; } - - /* Validate server view */ - if ((ServerView) && (ServerView->Length != sizeof(REMOTE_PORT_VIEW))) + else { - /* Fail */ - return STATUS_INVALID_PARAMETER; - } + CapturedQos = *SecurityQos; + /* NOTE: Do not care about CapturedQos.Length */ - /* Check if caller sent connection information length */ - if (ConnectionInformationLength) - { - /* Retrieve the input length */ - ConnectionInfoLength = *ConnectionInformationLength; + /* The following parameters are optional */ + + /* Capture the client view */ + if (ClientView != NULL) + { + /* Validate the size of the client view */ + if (ClientView->Length != sizeof(*ClientView)) + { + /* Invalid size */ + return STATUS_INVALID_PARAMETER; + } + CapturedClientView = *ClientView; + } + + /* Capture the server view */ + if (ServerView != NULL) + { + /* Validate the size of the server view */ + if (ServerView->Length != sizeof(*ServerView)) + { + /* Invalid size */ + return STATUS_INVALID_PARAMETER; + } + } + + /* Capture connection information length */ + if (ConnectionInformationLength) + ConnectionInfoLength = *ConnectionInformationLength; + + CapturedServerSid = ServerSid; } /* Get the port */ @@ -138,10 +239,14 @@ LpcPortObjectType, PreviousMode, NULL, - (PVOID *)&Port); + (PVOID*)&Port); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to reference port '%wZ': 0x%lx\n", PortName, Status); + + if (CapturedServerSid != ServerSid) + SepReleaseSid(CapturedServerSid, PreviousMode, TRUE); + return Status; } @@ -150,10 +255,14 @@ { /* It isn't, so fail */ ObDereferenceObject(Port); + + if (CapturedServerSid != ServerSid) + SepReleaseSid(CapturedServerSid, PreviousMode, TRUE); + return STATUS_INVALID_PORT_HANDLE; } - /* Check if we have a SID */ + /* Check if we have a (captured) SID */ if (ServerSid) { /* Make sure that we have a server */ @@ -161,11 +270,7 @@ { /* Get its token and query user information */ Token = PsReferencePrimaryToken(Port->ServerProcess); - //Status = SeQueryInformationToken(Token, TokenUser, (PVOID*)&TokenUserInfo); - // FIXME: Need SeQueryInformationToken - Status = STATUS_SUCCESS; - TokenUserInfo = ExAllocatePoolWithTag(PagedPool, sizeof(TOKEN_USER), TAG_SE); - TokenUserInfo->User.Sid = ServerSid; + Status = SeQueryInformationToken(Token, TokenUser, (PVOID*)&TokenUserInfo); PsDereferencePrimaryToken(Token); /* Check for success */ @@ -172,7 +277,7 @@ if (NT_SUCCESS(Status)) { /* Compare the SIDs */ - if (!RtlEqualSid(ServerSid, TokenUserInfo->User.Sid)) + if (!RtlEqualSid(CapturedServerSid, TokenUserInfo->User.Sid)) { /* Fail */ Status = STATUS_SERVER_SID_MISMATCH; @@ -188,6 +293,10 @@ 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)) { @@ -206,7 +315,7 @@ sizeof(LPCP_PORT_OBJECT), 0, 0, - (PVOID *)&ClientPort); + (PVOID*)&ClientPort); if (!NT_SUCCESS(Status)) { /* Failed, dereference the server port and return */ @@ -214,17 +323,20 @@ return Status; } - /* Setup the client port */ + /* + * Setup the client port -- From now on, dereferencing the client port + * will automatically dereference the connection port too. + */ RtlZeroMemory(ClientPort, sizeof(LPCP_PORT_OBJECT)); ClientPort->Flags = LPCP_CLIENT_PORT; ClientPort->ConnectionPort = Port; ClientPort->MaxMessageLength = Port->MaxMessageLength; - ClientPort->SecurityQos = *Qos; + ClientPort->SecurityQos = CapturedQos; InitializeListHead(&ClientPort->LpcReplyChainHead); InitializeListHead(&ClientPort->LpcDataInfoChainHead); /* Check if we have dynamic security */ - if (Qos->ContextTrackingMode == SECURITY_DYNAMIC_TRACKING) + if (CapturedQos.ContextTrackingMode == SECURITY_DYNAMIC_TRACKING) { /* Remember that */ ClientPort->Flags |= LPCP_SECURITY_DYNAMIC; @@ -233,7 +345,7 @@ { /* Create our own client security */ Status = SeCreateClientSecurity(Thread, - Qos, + &CapturedQos, FALSE, &ClientPort->StaticSecurity); if (!NT_SUCCESS(Status)) @@ -257,7 +369,7 @@ if (ClientView) { /* Get the section handle */ - Status = ObReferenceObjectByHandle(ClientView->SectionHandle, + Status = ObReferenceObjectByHandle(CapturedClientView.SectionHandle, SECTION_MAP_READ | SECTION_MAP_WRITE, MmSectionObjectType, @@ -267,12 +379,12 @@ if (!NT_SUCCESS(Status)) { /* Fail */ - ObDereferenceObject(Port); + ObDereferenceObject(ClientPort); return Status; } /* Set the section offset */ - SectionOffset.QuadPart = ClientView->SectionOffset; + SectionOffset.QuadPart = CapturedClientView.SectionOffset; /* Map it */ Status = MmMapViewOfSection(SectionToMap, @@ -281,13 +393,13 @@ 0, 0, &SectionOffset, - &ClientView->ViewSize, + &CapturedClientView.ViewSize, ViewUnmap, 0, PAGE_READWRITE); /* Update the offset */ - ClientView->SectionOffset = SectionOffset.LowPart; + CapturedClientView.SectionOffset = SectionOffset.LowPart; /* Check for failure */ if (!NT_SUCCESS(Status)) @@ -294,12 +406,12 @@ { /* Fail */ ObDereferenceObject(SectionToMap); - ObDereferenceObject(Port); + ObDereferenceObject(ClientPort); return Status; } /* Update the base */ - ClientView->ViewBase = ClientPort->ClientSectionBase; + CapturedClientView.ViewBase = ClientPort->ClientSectionBase; /* Reference and remember the process */ ClientPort->MappingProcess = PsGetCurrentProcess(); @@ -336,12 +448,12 @@ if (ClientView) { /* Set the view size */ - Message->Request.ClientViewSize = ClientView->ViewSize; + Message->Request.ClientViewSize = CapturedClientView.ViewSize; /* Copy the client view and clear the server view */ RtlCopyMemory(&ConnectMessage->ClientView, - ClientView, - sizeof(PORT_VIEW)); + &CapturedClientView, + sizeof(CapturedClientView)); RtlZeroMemory(&ConnectMessage->ServerView, sizeof(REMOTE_PORT_VIEW)); } else @@ -365,12 +477,33 @@ /* Check if we have connection information */ if (ConnectionInformation) { - /* Copy it in */ - RtlCopyMemory(ConnectMessage + 1, - ConnectionInformation, - ConnectionInfoLength); + _SEH2_TRY + { + /* Copy it in */ + RtlCopyMemory(ConnectMessage + 1, + ConnectionInformation, + ConnectionInfoLength); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Cleanup and return the exception code */ + + /* Free the message we have */ + LpcpFreeToPortZone(Message, 0); + + /* Dereference other objects */ + if (SectionToMap) ObDereferenceObject(SectionToMap); + ObDereferenceObject(ClientPort); + + /* Return status */ + _SEH2_YIELD(return _SEH2_GetExceptionCode()); + } + _SEH2_END; } + /* Reset the status code */ + Status = STATUS_SUCCESS; + /* Acquire the port lock */ KeAcquireGuardedMutex(&LpcpLock); @@ -395,7 +528,7 @@ InsertTailList(&Port->LpcReplyChainHead, &Thread->LpcReplyChain); Thread->LpcReplyMessage = Message; - /* Now we can finally reference the client port and link it*/ + /* Now we can finally reference the client port and link it */ ObReferenceObject(ClientPort); ConnectMessage->ClientPort = ClientPort; @@ -421,23 +554,36 @@ Status); /* If this is a waitable port, set the event */ - if (Port->Flags & LPCP_WAITABLE_PORT) KeSetEvent(&Port->WaitEvent, - 1, - FALSE); + if (Port->Flags & LPCP_WAITABLE_PORT) + KeSetEvent(&Port->WaitEvent, 1, FALSE); /* Release the queue semaphore and leave the critical region */ LpcpCompleteWait(Port->MsgQueue.Semaphore); KeLeaveCriticalRegion(); - /* Now wait for a reply */ + /* Now wait for a reply and set 'Status' */ LpcpConnectWait(&Thread->LpcReplySemaphore, PreviousMode); } + /* Now, always free the connection message */ + SectionToMap = LpcpFreeConMsg(&Message, &ConnectMessage, Thread); + /* Check for failure */ - if (!NT_SUCCESS(Status)) goto Cleanup; + if (!NT_SUCCESS(Status)) + { + /* Check if the semaphore got signaled in the meantime */ + if (KeReadStateSemaphore(&Thread->LpcReplySemaphore)) + { + /* Wait on it */ + KeWaitForSingleObject(&Thread->LpcReplySemaphore, + WrExecutive, + KernelMode, + FALSE, + NULL); + } - /* Free the connection message */ - SectionToMap = LpcpFreeConMsg(&Message, &ConnectMessage, Thread); + goto Failure; + } /* Check if we got a message back */ if (Message) @@ -451,20 +597,27 @@ sizeof(LPCP_CONNECTION_MESSAGE); } - /* Check if we had connection information */ + /* Check if the caller had connection information */ if (ConnectionInformation) { - /* Check if we had a length pointer */ - if (ConnectionInformationLength) + _SEH2_TRY { - /* Return the length */ - *ConnectionInformationLength = ConnectionInfoLength; + /* Return the connection information length if needed */ + if (ConnectionInformationLength) + *ConnectionInformationLength = ConnectionInfoLength; + + /* Return the connection information */ + RtlCopyMemory(ConnectionInformation, + ConnectMessage + 1, + ConnectionInfoLength); } - - /* Return the connection information */ - RtlCopyMemory(ConnectionInformation, - ConnectMessage + 1, - ConnectionInfoLength ); + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Cleanup and return the exception code */ + Status = _SEH2_GetExceptionCode(); + _SEH2_YIELD(goto Failure); + } + _SEH2_END; } /* Make sure we had a connected port */ @@ -478,37 +631,49 @@ NULL, PORT_ALL_ACCESS, 0, - (PVOID *)NULL, + NULL, &Handle); if (NT_SUCCESS(Status)) { - /* Return the handle */ - *PortHandle = Handle; LPCTRACE(LPC_CONNECT_DEBUG, "Handle: %p. Length: %lx\n", Handle, PortMessageLength); - /* Check if maximum length was requested */ - if (MaxMessageLength) *MaxMessageLength = PortMessageLength; + _SEH2_TRY + { + /* Return the handle */ + *PortHandle = Handle; - /* Check if we had a client view */ - if (ClientView) - { - /* Copy it back */ - RtlCopyMemory(ClientView, - &ConnectMessage->ClientView, - sizeof(PORT_VIEW)); + /* Check if maximum length was requested */ + if (MaxMessageLength) + *MaxMessageLength = PortMessageLength; + + /* Check if we had a client view */ + if (ClientView) + { + /* Copy it back */ + RtlCopyMemory(ClientView, + &ConnectMessage->ClientView, + sizeof(*ClientView)); + } + + /* Check if we had a server view */ + if (ServerView) + { + /* Copy it back */ + RtlCopyMemory(ServerView, + &ConnectMessage->ServerView, + sizeof(*ServerView)); + } } - - /* Check if we had a server view */ - if (ServerView) + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - /* Copy it back */ - RtlCopyMemory(ServerView, - &ConnectMessage->ServerView, - sizeof(REMOTE_PORT_VIEW)); + /* An exception happened, close the opened handle */ + ObCloseHandle(Handle, PreviousMode); + Status = _SEH2_GetExceptionCode(); } + _SEH2_END; } } else @@ -545,30 +710,16 @@ else { /* No reply message, fail */ - if (SectionToMap) ObDereferenceObject(SectionToMap); - ObDereferenceObject(ClientPort); Status = STATUS_PORT_CONNECTION_REFUSED; + goto Failure; } + ObDereferenceObject(Port); + /* Return status */ - ObDereferenceObject(Port); return Status; -Cleanup: - /* We failed, free the message */ - SectionToMap = LpcpFreeConMsg(&Message, &ConnectMessage, Thread); - - /* Check if the semaphore got signaled */ - if (KeReadStateSemaphore(&Thread->LpcReplySemaphore)) - { - /* Wait on it */ - KeWaitForSingleObject(&Thread->LpcReplySemaphore, - WrExecutive, - KernelMode, - FALSE, - NULL); - } - +Failure: /* Check if we had a message and free it */ if (Message) LpcpFreeToPortZone(Message, 0); @@ -575,9 +726,9 @@ /* Dereference other objects */ if (SectionToMap) ObDereferenceObject(SectionToMap); ObDereferenceObject(ClientPort); + ObDereferenceObject(Port); /* Return status */ - ObDereferenceObject(Port); return Status; } @@ -588,17 +739,17 @@ NTAPI NtConnectPort(OUT PHANDLE PortHandle, IN PUNICODE_STRING PortName, - IN PSECURITY_QUALITY_OF_SERVICE Qos, - IN PPORT_VIEW ClientView, - IN PREMOTE_PORT_VIEW ServerView, - OUT PULONG MaxMessageLength, - IN PVOID ConnectionInformation, - OUT PULONG ConnectionInformationLength) + IN PSECURITY_QUALITY_OF_SERVICE SecurityQos, + IN OUT PPORT_VIEW ClientView OPTIONAL, + IN OUT PREMOTE_PORT_VIEW ServerView OPTIONAL, + OUT PULONG MaxMessageLength OPTIONAL, + IN OUT PVOID ConnectionInformation OPTIONAL, + IN OUT PULONG ConnectionInformationLength OPTIONAL) { /* Call the newer API */ return NtSecureConnectPort(PortHandle, PortName, - Qos, + SecurityQos, ClientView, NULL, ServerView, Index: ntoskrnl/lpc/create.c =================================================================== --- ntoskrnl/lpc/create.c (révision 73151) +++ ntoskrnl/lpc/create.c (copie de travail) @@ -19,11 +19,12 @@ LpcpInitializePortQueue(IN PLPCP_PORT_OBJECT Port) { PLPCP_NONPAGED_PORT_QUEUE MessageQueue; + PAGED_CODE(); /* Allocate the queue */ MessageQueue = ExAllocatePoolWithTag(NonPagedPool, - sizeof(LPCP_NONPAGED_PORT_QUEUE), + sizeof(*MessageQueue), 'troP'); if (!MessageQueue) return STATUS_INSUFFICIENT_RESOURCES; @@ -46,15 +47,17 @@ IN ULONG MaxPoolUsage, IN BOOLEAN Waitable) { + NTSTATUS Status; KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); - NTSTATUS Status; + UNICODE_STRING CapturedObjectName, *ObjectName; PLPCP_PORT_OBJECT Port; HANDLE Handle; - PUNICODE_STRING ObjectName; - BOOLEAN NoName; + PAGED_CODE(); LPCTRACE(LPC_CREATE_DEBUG, "Name: %wZ\n", ObjectAttributes->ObjectName); + RtlInitEmptyUnicodeString(&CapturedObjectName, NULL, 0); + /* Check if the call comes from user mode */ if (PreviousMode != KernelMode) { @@ -63,15 +66,14 @@ /* 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); + /* Probe the ObjectAttributes and its object name (not the buffer) */ + ProbeForRead(ObjectAttributes, sizeof(*ObjectAttributes), sizeof(ULONG)); + ObjectName = ((volatile OBJECT_ATTRIBUTES*)ObjectAttributes)->ObjectName; + if (ObjectName) + { + ProbeForRead(ObjectName, sizeof(*ObjectName), 1); + CapturedObjectName = *(volatile UNICODE_STRING*)ObjectName; + } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -82,11 +84,14 @@ } else { - /* Check if we have no name */ - NoName = (ObjectAttributes->ObjectName->Buffer == NULL) || - (ObjectAttributes->ObjectName->Length == 0); + if (ObjectAttributes->ObjectName) + CapturedObjectName = *(ObjectAttributes->ObjectName); } + /* Normalize the buffer pointer in case we don't have a name */ + if (CapturedObjectName.Length == 0) + CapturedObjectName.Buffer = NULL; + /* Create the Object */ Status = ObCreateObject(PreviousMode, LpcPortObjectType, @@ -107,7 +112,7 @@ InitializeListHead(&Port->LpcReplyChainHead); /* Check if we don't have a name */ - if (NoName) + if (CapturedObjectName.Buffer == NULL) { /* Set up for an unconnected port */ Port->Flags = LPCP_UNCONNECTED_PORT; @@ -170,7 +175,7 @@ Port->MaxMessageLength = MaxMessageLength; /* Insert it now */ - Status = ObInsertObject((PVOID)Port, + Status = ObInsertObject(Port, NULL, PORT_ALL_ACCESS, 0, @@ -185,7 +190,8 @@ } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - ObCloseHandle(Handle, UserMode); + /* An exception happened, close the opened handle */ + ObCloseHandle(Handle, PreviousMode); Status = _SEH2_GetExceptionCode(); } _SEH2_END; Index: ntoskrnl/lpc/listen.c =================================================================== --- ntoskrnl/lpc/listen.c (révision 73151) +++ ntoskrnl/lpc/listen.c (copie de travail) @@ -23,10 +23,11 @@ OUT PPORT_MESSAGE ConnectMessage) { NTSTATUS Status; + PAGED_CODE(); LPCTRACE(LPC_LISTEN_DEBUG, "Handle: %p\n", PortHandle); - /* Wait forever for a connection request. */ + /* Wait forever for a connection request */ for (;;) { /* Do the wait */ @@ -35,13 +36,22 @@ NULL, ConnectMessage); - /* Accept only LPC_CONNECTION_REQUEST requests. */ - if ((Status != STATUS_SUCCESS) || - (LpcpGetMessageType(ConnectMessage) == LPC_CONNECTION_REQUEST)) + _SEH2_TRY { - /* Break out */ - break; + /* Accept only LPC_CONNECTION_REQUEST requests */ + if ((Status != STATUS_SUCCESS) || + (LpcpGetMessageType(ConnectMessage) == LPC_CONNECTION_REQUEST)) + { + /* Break out */ + _SEH2_YIELD(break); + } } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + _SEH2_YIELD(break); + } + _SEH2_END; } /* Return status */ @@ -48,5 +58,4 @@ return Status; } - /* EOF */ Index: ntoskrnl/lpc/port.c =================================================================== --- ntoskrnl/lpc/port.c (révision 73151) +++ ntoskrnl/lpc/port.c (copie de travail) @@ -60,6 +60,7 @@ NULL, &LpcPortObjectType); + /* Create the Waitable Port Object Type */ RtlInitUnicodeString(&Name, L"WaitablePort"); ObjectTypeInitializer.PoolType = NonPagedPool; ObjectTypeInitializer.DefaultNonPagedPoolCharge += sizeof(LPCP_PORT_OBJECT); @@ -125,37 +126,36 @@ NtImpersonateClientOfPort(IN HANDLE PortHandle, IN PPORT_MESSAGE ClientMessage) { - KPROCESSOR_MODE PreviousMode; + NTSTATUS Status; + KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); CLIENT_ID ClientId; ULONG MessageId; PLPCP_PORT_OBJECT Port = NULL, ConnectedPort = NULL; PETHREAD ClientThread = NULL; SECURITY_CLIENT_CONTEXT ClientContext; - NTSTATUS Status; + PAGED_CODE(); - /* Check the previous mode */ - PreviousMode = ExGetPreviousMode(); - if (PreviousMode == KernelMode) + /* Check if the call comes from user mode */ + if (PreviousMode != KernelMode) { - ClientId = ClientMessage->ClientId; - MessageId = ClientMessage->MessageId; - } - else - { _SEH2_TRY { ProbeForRead(ClientMessage, sizeof(*ClientMessage), sizeof(PVOID)); - ClientId = ClientMessage->ClientId; - MessageId = ClientMessage->MessageId; + ClientId = ((volatile PORT_MESSAGE*)ClientMessage)->ClientId; + MessageId = ((volatile PORT_MESSAGE*)ClientMessage)->MessageId; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - DPRINT1("Got exception!\n"); _SEH2_YIELD(return _SEH2_GetExceptionCode()); } _SEH2_END; } + else + { + ClientId = ClientMessage->ClientId; + MessageId = ClientMessage->MessageId; + } /* Reference the port handle */ Status = ObReferenceObjectByHandle(PortHandle, @@ -192,8 +192,7 @@ /* Get the connected port and try to reference it */ ConnectedPort = Port->ConnectedPort; - if ((ConnectedPort == NULL) || - !ObReferenceObjectSafe(ConnectedPort)) + if ((ConnectedPort == NULL) || !ObReferenceObjectSafe(ConnectedPort)) { DPRINT1("Failed to reference the connected port\n"); ConnectedPort = NULL; @@ -254,13 +253,6 @@ /* Get rid of the security context */ SeDeleteClientSecurity(&ClientContext); - goto Cleanup; - -CleanupWithLock: - - /* Release the lock */ - KeReleaseGuardedMutex(&LpcpLock); - Cleanup: if (ConnectedPort != NULL) @@ -272,6 +264,12 @@ ObDereferenceObject(Port); return Status; + +CleanupWithLock: + + /* Release the lock */ + KeReleaseGuardedMutex(&LpcpLock); + goto Cleanup; } NTSTATUS Index: ntoskrnl/lpc/reply.c =================================================================== --- ntoskrnl/lpc/reply.c (révision 73151) +++ ntoskrnl/lpc/reply.c (copie de travail) @@ -99,6 +99,7 @@ { PLPCP_MESSAGE Message; PLIST_ENTRY ListEntry; + PAGED_CODE(); /* Check if the port we want is the connection port */ @@ -141,7 +142,6 @@ IN ULONG MessageType, IN PCLIENT_ID ClientId) { - /* Set the Message size */ LPCTRACE((LPC_REPLY_DEBUG | LPC_SEND_DEBUG), "Destination/Origin: %p/%p. Data: %p. Length: %lx\n", Destination, @@ -148,6 +148,8 @@ Origin, Data, Origin->u1.Length); + + /* Set the Message size */ Destination->u1.Length = Origin->u1.Length; /* Set the Message Type */ @@ -188,12 +190,12 @@ NtReplyPort(IN HANDLE PortHandle, IN PPORT_MESSAGE ReplyMessage) { + NTSTATUS Status; + KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); + PORT_MESSAGE CapturedReplyMessage; PLPCP_PORT_OBJECT Port; - KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); - NTSTATUS Status; PLPCP_MESSAGE Message; PETHREAD Thread = PsGetCurrentThread(), WakeupThread; - //PORT_MESSAGE CapturedReplyMessage; PAGED_CODE(); LPCTRACE(LPC_REPLY_DEBUG, @@ -201,25 +203,28 @@ PortHandle, ReplyMessage); - if (KeGetPreviousMode() == UserMode) + /* Check if the call comes from user mode */ + if (PreviousMode != KernelMode) { _SEH2_TRY { - ProbeForRead(ReplyMessage, sizeof(PORT_MESSAGE), sizeof(ULONG)); - /*RtlCopyMemory(&CapturedReplyMessage, ReplyMessage, sizeof(PORT_MESSAGE)); - ReplyMessage = &CapturedReplyMessage;*/ + ProbeForRead(ReplyMessage, sizeof(*ReplyMessage), sizeof(ULONG)); + CapturedReplyMessage = *(volatile PORT_MESSAGE*)ReplyMessage; } - _SEH2_EXCEPT(ExSystemExceptionFilter()) + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - DPRINT1("SEH crash [1]\n"); _SEH2_YIELD(return _SEH2_GetExceptionCode()); } _SEH2_END; } + else + { + CapturedReplyMessage = *ReplyMessage; + } /* Validate its length */ - if (((ULONG)ReplyMessage->u1.s1.DataLength + sizeof(PORT_MESSAGE)) > - (ULONG)ReplyMessage->u1.s1.TotalLength) + if (((ULONG)CapturedReplyMessage.u1.s1.DataLength + sizeof(PORT_MESSAGE)) > + (ULONG)CapturedReplyMessage.u1.s1.TotalLength) { /* Fail */ return STATUS_INVALID_PARAMETER; @@ -226,7 +231,7 @@ } /* Make sure it has a valid ID */ - if (!ReplyMessage->MessageId) return STATUS_INVALID_PARAMETER; + if (!CapturedReplyMessage.MessageId) return STATUS_INVALID_PARAMETER; /* Get the Port object */ Status = ObReferenceObjectByHandle(PortHandle, @@ -238,9 +243,9 @@ if (!NT_SUCCESS(Status)) return Status; /* Validate its length in respect to the port object */ - if (((ULONG)ReplyMessage->u1.s1.TotalLength > Port->MaxMessageLength) || - ((ULONG)ReplyMessage->u1.s1.TotalLength <= - (ULONG)ReplyMessage->u1.s1.DataLength)) + if (((ULONG)CapturedReplyMessage.u1.s1.TotalLength > Port->MaxMessageLength) || + ((ULONG)CapturedReplyMessage.u1.s1.TotalLength <= + (ULONG)CapturedReplyMessage.u1.s1.DataLength)) { /* Too large, fail */ ObDereferenceObject(Port); @@ -248,7 +253,7 @@ } /* Get the ETHREAD corresponding to it */ - Status = PsLookupProcessThreadByCid(&ReplyMessage->ClientId, + Status = PsLookupProcessThreadByCid(&CapturedReplyMessage.ClientId, NULL, &WakeupThread); if (!NT_SUCCESS(Status)) @@ -272,10 +277,10 @@ KeAcquireGuardedMutex(&LpcpLock); /* Make sure this is the reply the thread is waiting for */ - if ((WakeupThread->LpcReplyMessageId != ReplyMessage->MessageId) || + if ((WakeupThread->LpcReplyMessageId != CapturedReplyMessage.MessageId) || ((LpcpGetMessageFromThread(WakeupThread)) && - (LpcpGetMessageType(&LpcpGetMessageFromThread(WakeupThread)-> - Request) != LPC_REQUEST))) + (LpcpGetMessageType(&LpcpGetMessageFromThread(WakeupThread)-> Request) + != LPC_REQUEST))) { /* It isn't, fail */ LpcpFreeToPortZone(Message, LPCP_LOCK_HELD | LPCP_LOCK_RELEASE); @@ -288,7 +293,7 @@ _SEH2_TRY { LpcpMoveMessage(&Message->Request, - ReplyMessage, + &CapturedReplyMessage, ReplyMessage + 1, LPC_REPLY, NULL); @@ -295,7 +300,7 @@ } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - /* Fail */ + /* Cleanup and return the exception code */ LpcpFreeToPortZone(Message, LPCP_LOCK_HELD | LPCP_LOCK_RELEASE); ObDereferenceObject(WakeupThread); ObDereferenceObject(Port); @@ -322,7 +327,7 @@ /* Check if this is the message the thread had received */ if ((Thread->LpcReceivedMsgIdValid) && - (Thread->LpcReceivedMessageId == ReplyMessage->MessageId)) + (Thread->LpcReceivedMessageId == CapturedReplyMessage.MessageId)) { /* Clear this data */ Thread->LpcReceivedMessageId = 0; @@ -331,9 +336,9 @@ /* Free any data information */ LpcpFreeDataInfoMessage(Port, - ReplyMessage->MessageId, - ReplyMessage->CallbackId, - ReplyMessage->ClientId); + CapturedReplyMessage.MessageId, + CapturedReplyMessage.CallbackId, + CapturedReplyMessage.ClientId); /* Release the lock and release the LPC semaphore to wake up waiters */ KeReleaseGuardedMutex(&LpcpLock); @@ -358,15 +363,15 @@ OUT PPORT_MESSAGE ReceiveMessage, IN PLARGE_INTEGER Timeout OPTIONAL) { + NTSTATUS Status; + KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(), WaitMode = PreviousMode; + PORT_MESSAGE CapturedReplyMessage; + LARGE_INTEGER CapturedTimeout; PLPCP_PORT_OBJECT Port, ReceivePort, ConnectionPort = NULL; - KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(), WaitMode = PreviousMode; - NTSTATUS Status; PLPCP_MESSAGE Message; PETHREAD Thread = PsGetCurrentThread(), WakeupThread; PLPCP_CONNECTION_MESSAGE ConnectMessage; ULONG ConnectionInfoLength; - //PORT_MESSAGE CapturedReplyMessage; - LARGE_INTEGER CapturedTimeout; PAGED_CODE(); LPCTRACE(LPC_REPLY_DEBUG, @@ -376,30 +381,29 @@ ReceiveMessage, PortContext); - if (KeGetPreviousMode() == UserMode) + /* Check if the call comes from user mode */ + if (PreviousMode != KernelMode) { _SEH2_TRY { + if (PortContext != NULL) + ProbeForWritePointer(PortContext); + if (ReplyMessage != NULL) { - ProbeForRead(ReplyMessage, sizeof(PORT_MESSAGE), sizeof(ULONG)); - /*RtlCopyMemory(&CapturedReplyMessage, ReplyMessage, sizeof(PORT_MESSAGE)); - ReplyMessage = &CapturedReplyMessage;*/ + ProbeForRead(ReplyMessage, sizeof(*ReplyMessage), sizeof(ULONG)); + CapturedReplyMessage = *(volatile PORT_MESSAGE*)ReplyMessage; } if (Timeout != NULL) { ProbeForReadLargeInteger(Timeout); - RtlCopyMemory(&CapturedTimeout, Timeout, sizeof(LARGE_INTEGER)); + CapturedTimeout = *(volatile LARGE_INTEGER*)Timeout; Timeout = &CapturedTimeout; } - - if (PortContext != NULL) - ProbeForWritePointer(PortContext); } - _SEH2_EXCEPT(ExSystemExceptionFilter()) + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - DPRINT1("SEH crash [1]\n"); _SEH2_YIELD(return _SEH2_GetExceptionCode()); } _SEH2_END; @@ -408,6 +412,9 @@ { /* If this is a system thread, then let it page out its stack */ if (Thread->SystemThread) WaitMode = UserMode; + + if (ReplyMessage != NULL) + CapturedReplyMessage = *ReplyMessage; } /* Check if caller has a reply message */ @@ -414,8 +421,8 @@ if (ReplyMessage) { /* Validate its length */ - if (((ULONG)ReplyMessage->u1.s1.DataLength + sizeof(PORT_MESSAGE)) > - (ULONG)ReplyMessage->u1.s1.TotalLength) + if (((ULONG)CapturedReplyMessage.u1.s1.DataLength + sizeof(PORT_MESSAGE)) > + (ULONG)CapturedReplyMessage.u1.s1.TotalLength) { /* Fail */ return STATUS_INVALID_PARAMETER; @@ -422,7 +429,7 @@ } /* Make sure it has a valid ID */ - if (!ReplyMessage->MessageId) return STATUS_INVALID_PARAMETER; + if (!CapturedReplyMessage.MessageId) return STATUS_INVALID_PARAMETER; } /* Get the Port object */ @@ -438,9 +445,9 @@ if (ReplyMessage) { /* Validate its length in respect to the port object */ - if (((ULONG)ReplyMessage->u1.s1.TotalLength > Port->MaxMessageLength) || - ((ULONG)ReplyMessage->u1.s1.TotalLength <= - (ULONG)ReplyMessage->u1.s1.DataLength)) + if (((ULONG)CapturedReplyMessage.u1.s1.TotalLength > Port->MaxMessageLength) || + ((ULONG)CapturedReplyMessage.u1.s1.TotalLength <= + (ULONG)CapturedReplyMessage.u1.s1.DataLength)) { /* Too large, fail */ ObDereferenceObject(Port); @@ -488,7 +495,7 @@ if (ReplyMessage) { /* Get the ETHREAD corresponding to it */ - Status = PsLookupProcessThreadByCid(&ReplyMessage->ClientId, + Status = PsLookupProcessThreadByCid(&CapturedReplyMessage.ClientId, NULL, &WakeupThread); if (!NT_SUCCESS(Status)) @@ -514,10 +521,10 @@ KeAcquireGuardedMutex(&LpcpLock); /* Make sure this is the reply the thread is waiting for */ - if ((WakeupThread->LpcReplyMessageId != ReplyMessage->MessageId) || + if ((WakeupThread->LpcReplyMessageId != CapturedReplyMessage.MessageId) || ((LpcpGetMessageFromThread(WakeupThread)) && - (LpcpGetMessageType(&LpcpGetMessageFromThread(WakeupThread)-> - Request) != LPC_REQUEST))) + (LpcpGetMessageType(&LpcpGetMessageFromThread(WakeupThread)->Request) + != LPC_REQUEST))) { /* It isn't, fail */ LpcpFreeToPortZone(Message, LPCP_LOCK_HELD | LPCP_LOCK_RELEASE); @@ -528,11 +535,24 @@ } /* Copy the message */ - LpcpMoveMessage(&Message->Request, - ReplyMessage, - ReplyMessage + 1, - LPC_REPLY, - NULL); + _SEH2_TRY + { + LpcpMoveMessage(&Message->Request, + &CapturedReplyMessage, + ReplyMessage + 1, + LPC_REPLY, + NULL); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Cleanup and return the exception code */ + LpcpFreeToPortZone(Message, LPCP_LOCK_HELD | LPCP_LOCK_RELEASE); + if (ConnectionPort) ObDereferenceObject(ConnectionPort); + ObDereferenceObject(WakeupThread); + ObDereferenceObject(Port); + _SEH2_YIELD(return _SEH2_GetExceptionCode()); + } + _SEH2_END; /* Reference the thread while we use it */ ObReferenceObject(WakeupThread); @@ -553,7 +573,7 @@ /* Check if this is the message the thread had received */ if ((Thread->LpcReceivedMsgIdValid) && - (Thread->LpcReceivedMessageId == ReplyMessage->MessageId)) + (Thread->LpcReceivedMessageId == CapturedReplyMessage.MessageId)) { /* Clear this data */ Thread->LpcReceivedMessageId = 0; @@ -562,9 +582,9 @@ /* Free any data information */ LpcpFreeDataInfoMessage(Port, - ReplyMessage->MessageId, - ReplyMessage->CallbackId, - ReplyMessage->ClientId); + CapturedReplyMessage.MessageId, + CapturedReplyMessage.CallbackId, + CapturedReplyMessage.ClientId); /* Release the lock and release the LPC semaphore to wake up waiters */ KeReleaseGuardedMutex(&LpcpLock); @@ -599,8 +619,7 @@ } /* Get the message on the queue */ - Message = CONTAINING_RECORD(RemoveHeadList(&ReceivePort-> - MsgQueue.ReceiveHead), + Message = CONTAINING_RECORD(RemoveHeadList(&ReceivePort->MsgQueue.ReceiveHead), LPCP_MESSAGE, Entry); @@ -687,9 +706,8 @@ ASSERT(FALSE); } } - _SEH2_EXCEPT(ExSystemExceptionFilter()) + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - DPRINT1("SEH crash [2]\n"); Status = _SEH2_GetExceptionCode(); } _SEH2_END; @@ -756,39 +774,38 @@ IN ULONG Index, IN PVOID Buffer, IN ULONG BufferLength, - OUT PULONG Returnlength) + OUT PULONG ReturnLength) { - KPROCESSOR_MODE PreviousMode; + NTSTATUS Status; + KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); PORT_MESSAGE CapturedMessage; PLPCP_PORT_OBJECT Port = NULL; PETHREAD ClientThread = NULL; - SIZE_T LocalReturnlength; + SIZE_T LocalReturnLength; PLPCP_MESSAGE InfoMessage; PLPCP_DATA_INFO DataInfo; PVOID DataInfoBaseAddress; - NTSTATUS Status; + PAGED_CODE(); - /* Check the previous mode */ - PreviousMode = ExGetPreviousMode(); - if (PreviousMode == KernelMode) + /* Check if the call comes from user mode */ + if (PreviousMode != KernelMode) { - CapturedMessage = *Message; - } - else - { _SEH2_TRY { ProbeForRead(Message, sizeof(*Message), sizeof(PVOID)); - CapturedMessage = *Message; + CapturedMessage = *(volatile PORT_MESSAGE*)Message; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - DPRINT1("Got exception!\n"); _SEH2_YIELD(return _SEH2_GetExceptionCode()); } _SEH2_END; } + else + { + CapturedMessage = *Message; + } /* Make sure there is any data to copy */ if (CapturedMessage.u2.s2.DataInfoOffset == 0) @@ -889,7 +906,7 @@ DataInfoBaseAddress, BufferLength, PreviousMode, - &LocalReturnlength); + &LocalReturnLength); } else { @@ -900,7 +917,7 @@ Buffer, BufferLength, PreviousMode, - &LocalReturnlength); + &LocalReturnLength); } if (!NT_SUCCESS(Status)) @@ -910,16 +927,16 @@ } /* Check if the caller asked to return the copied length */ - if (Returnlength != NULL) + if (ReturnLength != NULL) { _SEH2_TRY { - *Returnlength = LocalReturnlength; + *ReturnLength = LocalReturnLength; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Ignore */ - DPRINT1("Exception writing Returnlength, ignoring\n"); + DPRINT1("Exception writing ReturnLength, ignoring\n"); } _SEH2_END; } @@ -941,7 +958,7 @@ } /* - * @unimplemented + * @implemented */ NTSTATUS NTAPI @@ -963,7 +980,7 @@ } /* - * @unimplemented + * @implemented */ NTSTATUS NTAPI Index: ntoskrnl/lpc/send.c =================================================================== --- ntoskrnl/lpc/send.c (révision 73151) +++ ntoskrnl/lpc/send.c (copie de travail) @@ -179,18 +179,18 @@ IN PPORT_MESSAGE LpcRequest, OUT PPORT_MESSAGE LpcReply) { - PLPCP_PORT_OBJECT Port, QueuePort, ReplyPort, ConnectionPort = NULL; - KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); NTSTATUS Status = STATUS_SUCCESS; + PLPCP_PORT_OBJECT Port = (PLPCP_PORT_OBJECT)PortObject; + PLPCP_PORT_OBJECT QueuePort, ReplyPort, ConnectionPort = NULL; PLPCP_MESSAGE Message; + KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); PETHREAD Thread = PsGetCurrentThread(); BOOLEAN Callback = FALSE; PKSEMAPHORE Semaphore; USHORT MessageType; + PAGED_CODE(); - Port = (PLPCP_PORT_OBJECT)PortObject; - LPCTRACE(LPC_SEND_DEBUG, "Port: %p. Messages: %p/%p. Type: %lx\n", Port, @@ -205,33 +205,26 @@ MessageType = LpcpGetMessageType(LpcRequest); switch (MessageType) { - /* No type */ + /* No type, assume LPC request */ case 0: - - /* Assume LPC request */ MessageType = LPC_REQUEST; break; /* LPC request callback */ case LPC_REQUEST: - - /* This is a callback */ Callback = TRUE; break; - /* Anything else */ + /* Anything else, nothing to do */ case LPC_CLIENT_DIED: case LPC_PORT_CLOSED: case LPC_EXCEPTION: case LPC_DEBUG_EVENT: case LPC_ERROR_EVENT: - - /* Nothing to do */ break; + /* Invalid message type */ default: - - /* Invalid message type */ return STATUS_INVALID_PARAMETER; } @@ -448,15 +441,14 @@ IN PPORT_MESSAGE LpcRequest) { NTSTATUS Status; + KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); + PETHREAD Thread = PsGetCurrentThread(); + PORT_MESSAGE CapturedLpcRequest; PLPCP_PORT_OBJECT Port, QueuePort, ConnectionPort = NULL; ULONG MessageType; PLPCP_MESSAGE Message; - KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); - PETHREAD Thread = PsGetCurrentThread(); - PORT_MESSAGE CapturedLpcRequest; PAGED_CODE(); - LPCTRACE(LPC_SEND_DEBUG, "Handle: %p. Message: %p. Type: %lx\n", PortHandle, @@ -469,9 +461,8 @@ _SEH2_TRY { /* Probe and capture the LpcRequest */ - ProbeForRead(LpcRequest, sizeof(PORT_MESSAGE), sizeof(ULONG)); - ProbeForRead(LpcRequest, LpcRequest->u1.s1.TotalLength, sizeof(ULONG)); - CapturedLpcRequest = *LpcRequest; + ProbeForRead(LpcRequest, sizeof(*LpcRequest), sizeof(ULONG)); + CapturedLpcRequest = *(volatile PORT_MESSAGE*)LpcRequest; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -531,7 +522,7 @@ { /* Copy it */ LpcpMoveMessage(&Message->Request, - LpcRequest, + &CapturedLpcRequest, LpcRequest + 1, MessageType, &Thread->Cid); @@ -538,7 +529,7 @@ } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - /* Fail */ + /* Cleanup and return the exception code */ LpcpFreeToPortZone(Message, 0); ObDereferenceObject(Port); _SEH2_YIELD(return _SEH2_GetExceptionCode()); @@ -578,8 +569,7 @@ return STATUS_PORT_DISCONNECTED; } } - else if ((Port->Flags & LPCP_PORT_TYPE_MASK) != - LPCP_COMMUNICATION_PORT) + else if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_COMMUNICATION_PORT) { /* Use the connection port for anything but communication ports */ ConnectionPort = QueuePort = Port->ConnectionPort; @@ -706,17 +696,18 @@ IN PPORT_MESSAGE LpcRequest, IN OUT PPORT_MESSAGE LpcReply) { - PORT_MESSAGE LocalLpcRequest; + NTSTATUS Status; + PORT_MESSAGE CapturedLpcRequest; ULONG NumberOfDataEntries; PLPCP_PORT_OBJECT Port, QueuePort, ReplyPort, ConnectionPort = NULL; + PLPCP_MESSAGE Message; KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); - NTSTATUS Status; - PLPCP_MESSAGE Message; PETHREAD Thread = PsGetCurrentThread(); BOOLEAN Callback; PKSEMAPHORE Semaphore; ULONG MessageType; PLPCP_DATA_INFO DataInfo; + PAGED_CODE(); LPCTRACE(LPC_SEND_DEBUG, "Handle: %p. Messages: %p/%p. Type: %lx\n", @@ -733,10 +724,9 @@ { _SEH2_TRY { - /* Probe the full request message and copy the base structure */ + /* Probe and capture the LpcRequest */ ProbeForRead(LpcRequest, sizeof(*LpcRequest), sizeof(ULONG)); - ProbeForRead(LpcRequest, LpcRequest->u1.s1.TotalLength, sizeof(ULONG)); - LocalLpcRequest = *LpcRequest; + CapturedLpcRequest = *(volatile PORT_MESSAGE*)LpcRequest; /* Probe the reply message for write */ ProbeForWrite(LpcReply, sizeof(*LpcReply), sizeof(ULONG)); @@ -758,7 +748,7 @@ } else { - LocalLpcRequest = *LpcRequest; + CapturedLpcRequest = *LpcRequest; Status = LpcpVerifyMessageDataInfo(LpcRequest, &NumberOfDataEntries); if (!NT_SUCCESS(Status)) { @@ -768,15 +758,15 @@ } /* This flag is undocumented. Remove it before continuing */ - LocalLpcRequest.u2.s2.Type &= ~0x4000; + CapturedLpcRequest.u2.s2.Type &= ~0x4000; /* Check if this is an LPC Request */ - if (LpcpGetMessageType(&LocalLpcRequest) == LPC_REQUEST) + if (LpcpGetMessageType(&CapturedLpcRequest) == LPC_REQUEST) { /* Then it's a callback */ Callback = TRUE; } - else if (LpcpGetMessageType(&LocalLpcRequest)) + else if (LpcpGetMessageType(&CapturedLpcRequest)) { /* This is a not kernel-mode message */ DPRINT1("Not a kernel-mode message!\n"); @@ -785,24 +775,24 @@ else { /* This is a kernel-mode message without a callback */ - LocalLpcRequest.u2.s2.Type |= LPC_REQUEST; + CapturedLpcRequest.u2.s2.Type |= LPC_REQUEST; Callback = FALSE; } /* Get the message type */ - MessageType = LocalLpcRequest.u2.s2.Type; + MessageType = CapturedLpcRequest.u2.s2.Type; /* Due to the above probe, we know that TotalLength is positive */ - ASSERT(LocalLpcRequest.u1.s1.TotalLength >= 0); + ASSERT(CapturedLpcRequest.u1.s1.TotalLength >= 0); /* Validate the length */ - if ((((ULONG)(USHORT)LocalLpcRequest.u1.s1.DataLength + sizeof(PORT_MESSAGE)) > - (ULONG)LocalLpcRequest.u1.s1.TotalLength)) + if ((((ULONG)(USHORT)CapturedLpcRequest.u1.s1.DataLength + sizeof(PORT_MESSAGE)) > + (ULONG)CapturedLpcRequest.u1.s1.TotalLength)) { /* Fail */ DPRINT1("Invalid message length: %u, %u\n", - LocalLpcRequest.u1.s1.DataLength, - LocalLpcRequest.u1.s1.TotalLength); + CapturedLpcRequest.u1.s1.DataLength, + CapturedLpcRequest.u1.s1.TotalLength); return STATUS_INVALID_PARAMETER; } @@ -816,13 +806,13 @@ if (!NT_SUCCESS(Status)) return Status; /* Validate the message length */ - if (((ULONG)LocalLpcRequest.u1.s1.TotalLength > Port->MaxMessageLength) || - ((ULONG)LocalLpcRequest.u1.s1.TotalLength <= (ULONG)LocalLpcRequest.u1.s1.DataLength)) + if (((ULONG)CapturedLpcRequest.u1.s1.TotalLength > Port->MaxMessageLength) || + ((ULONG)CapturedLpcRequest.u1.s1.TotalLength <= (ULONG)CapturedLpcRequest.u1.s1.DataLength)) { /* Fail */ DPRINT1("Invalid message length: %u, %u\n", - LocalLpcRequest.u1.s1.DataLength, - LocalLpcRequest.u1.s1.TotalLength); + CapturedLpcRequest.u1.s1.DataLength, + CapturedLpcRequest.u1.s1.TotalLength); ObDereferenceObject(Port); return STATUS_PORT_MESSAGE_TOO_LONG; } @@ -874,7 +864,7 @@ } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - /* Fail */ + /* Cleanup and return the exception code */ DPRINT1("Got exception!\n"); LpcpFreeToPortZone(Message, 0); ObDereferenceObject(Port); Index: sdk/include/ndk/lpcfuncs.h =================================================================== --- sdk/include/ndk/lpcfuncs.h (révision 73151) +++ sdk/include/ndk/lpcfuncs.h (copie de travail) @@ -56,8 +56,8 @@ _In_opt_ PVOID PortContext, _In_ PPORT_MESSAGE ConnectionRequest, _In_ BOOLEAN AcceptConnection, - _In_opt_ PPORT_VIEW ServerView, - _In_opt_ PREMOTE_PORT_VIEW ClientView + _Inout_opt_ PPORT_VIEW ServerView, + _Out_opt_ PREMOTE_PORT_VIEW ClientView ); NTSYSCALLAPI @@ -74,11 +74,11 @@ _Out_ PHANDLE PortHandle, _In_ PUNICODE_STRING PortName, _In_ PSECURITY_QUALITY_OF_SERVICE SecurityQos, - _In_opt_ PPORT_VIEW ClientView, - _In_opt_ PREMOTE_PORT_VIEW ServerView, - _In_opt_ PULONG MaxMessageLength, - _In_opt_ PVOID ConnectionInformation, - _In_opt_ PULONG ConnectionInformationLength + _Inout_opt_ PPORT_VIEW ClientView, + _Inout_opt_ PREMOTE_PORT_VIEW ServerView, + _Out_opt_ PULONG MaxMessageLength, + _Inout_opt_ PVOID ConnectionInformation, + _Inout_opt_ PULONG ConnectionInformationLength ); NTSYSCALLAPI @@ -209,12 +209,12 @@ _Out_ PHANDLE PortHandle, _In_ PUNICODE_STRING PortName, _In_ PSECURITY_QUALITY_OF_SERVICE SecurityQos, - _In_opt_ PPORT_VIEW ClientView, + _Inout_opt_ PPORT_VIEW ClientView, _In_opt_ PSID Sid, - _In_opt_ PREMOTE_PORT_VIEW ServerView, - _In_opt_ PULONG MaxMessageLength, - _In_opt_ PVOID ConnectionInformation, - _Out_opt_ PULONG ConnectionInformationLength + _Inout_opt_ PREMOTE_PORT_VIEW ServerView, + _Out_opt_ PULONG MaxMessageLength, + _Inout_opt_ PVOID ConnectionInformation, + _Inout_opt_ PULONG ConnectionInformationLength ); NTSYSCALLAPI