[NTOS:LPC] Ensure debug-traced pointer-given user-mode data is captured. (#4399)

CORE-18098
This commit is contained in:
Hermès Bélusca-Maïto 2022-03-20 22:55:06 +01:00
parent e4d572a432
commit b3c55b9e6c
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
3 changed files with 74 additions and 38 deletions

View file

@ -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,22 +311,28 @@ 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);
}
#if DBG
ReleaseCapturedUnicodeString(&CapturedPortName, PreviousMode);
#endif
/* Check if SID failed */
if (!NT_SUCCESS(Status))
if (ServerSid && !NT_SUCCESS(Status))
{
/* Quit */
ObDereferenceObject(Port);
return Status;
}
}
/* Create the client port */
Status = ObCreateObject(PreviousMode,

View file

@ -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,

View file

@ -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;