- DbgkpSendApiMessage/Lpc: Modification of EPROCESS flags must be interlocked, use PspSetProcessFlag.

- DbgkMap/UnmapViewOfSection: Don't check for the DeadThread flag, doing so is only necessary during early thread creation.
- DbgkCreateThread: Set the StartAddress pointer in the case where we only send the Create Thread message. Also, we should receive the target thread as the first parameter.
- NtDebugActiveProcess: Don't allow debugging the current process.
- NtDebugContinue: We should signal the Debug Object, not the Debug Event. Also make sure we pass the correct event to DbgkpWakeTarget.
- NtWaitForDebugEvent: Cleanup probe and capture of the input timeout.

svn path=/trunk/; revision=38768
This commit is contained in:
Stefan Ginsberg 2009-01-15 13:14:37 +00:00
parent a0520cb3ae
commit 3c445f492d
4 changed files with 69 additions and 62 deletions

View file

@ -219,7 +219,7 @@ DbgkpSendApiMessageLpc(IN OUT PDBGKM_MSG Message,
Message->ReturnedStatus = STATUS_PENDING; Message->ReturnedStatus = STATUS_PENDING;
/* Set create process reported state */ /* Set create process reported state */
PsGetCurrentProcess()->CreateReported = TRUE; PspSetProcessFlag(PsGetCurrentProcess(), PSF_CREATE_REPORTED_BIT);
/* Send the LPC command */ /* Send the LPC command */
Status = LpcRequestWaitReplyPort(Port, Status = LpcRequestWaitReplyPort(Port,
@ -254,7 +254,7 @@ DbgkpSendApiMessage(IN OUT PDBGKM_MSG ApiMsg,
ApiMsg->ReturnedStatus = STATUS_PENDING; ApiMsg->ReturnedStatus = STATUS_PENDING;
/* Set create process reported state */ /* Set create process reported state */
PsGetCurrentProcess()->CreateReported = TRUE; PspSetProcessFlag(PsGetCurrentProcess(), PSF_CREATE_REPORTED_BIT);
/* Send the LPC command */ /* Send the LPC command */
Status = DbgkpQueueMessage(PsGetCurrentProcess(), Status = DbgkpQueueMessage(PsGetCurrentProcess(),
@ -1081,6 +1081,7 @@ DbgkpCloseObject(IN PEPROCESS OwnerProcess OPTIONAL,
BOOLEAN DebugPortCleared = FALSE; BOOLEAN DebugPortCleared = FALSE;
PLIST_ENTRY DebugEventList; PLIST_ENTRY DebugEventList;
PDEBUG_EVENT DebugEvent; PDEBUG_EVENT DebugEvent;
PAGED_CODE();
DBGKTRACE(DBGK_OBJECT_DEBUG, "OwnerProcess: %p DebugObject: %p\n", DBGKTRACE(DBGK_OBJECT_DEBUG, "OwnerProcess: %p DebugObject: %p\n",
OwnerProcess, DebugObject); OwnerProcess, DebugObject);
@ -1260,8 +1261,9 @@ ThreadScan:
else else
{ {
/* Set the process flags */ /* Set the process flags */
InterlockedOr((PLONG)&Process->Flags, PspSetProcessFlag(Process,
PSF_NO_DEBUG_INHERIT_BIT | PSF_CREATE_REPORTED_BIT); PSF_NO_DEBUG_INHERIT_BIT |
PSF_CREATE_REPORTED_BIT);
/* Reference the debug object */ /* Reference the debug object */
ObReferenceObject(DebugObject); ObReferenceObject(DebugObject);
@ -1474,12 +1476,15 @@ NtCreateDebugObject(OUT PHANDLE DebugHandle,
&hDebug); &hDebug);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
/* Enter SEH to protect the write */
_SEH2_TRY _SEH2_TRY
{ {
/* Return the handle */
*DebugHandle = hDebug; *DebugHandle = hDebug;
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(ExSystemExceptionFilter())
{ {
/* Get the exception code */
Status = _SEH2_GetExceptionCode(); Status = _SEH2_GetExceptionCode();
} _SEH2_END; } _SEH2_END;
} }
@ -1570,7 +1575,7 @@ NtDebugContinue(IN HANDLE DebugHandle,
{ {
/* Wake it up and break out */ /* Wake it up and break out */
DebugEvent->Flags &= ~DEBUG_EVENT_INACTIVE; DebugEvent->Flags &= ~DEBUG_EVENT_INACTIVE;
KeSetEvent(&DebugEvent->ContinueEvent, KeSetEvent(&DebugObject->EventsPresent,
IO_NO_INCREMENT, IO_NO_INCREMENT,
FALSE); FALSE);
break; break;
@ -1603,11 +1608,11 @@ NtDebugContinue(IN HANDLE DebugHandle,
if (NeedsWake) if (NeedsWake)
{ {
/* Set the continue status */ /* Set the continue status */
DebugEvent->ApiMsg.ReturnedStatus = ContinueStatus; DebugEventToWake->ApiMsg.ReturnedStatus = ContinueStatus;
DebugEvent->Status = STATUS_SUCCESS; DebugEventToWake->Status = STATUS_SUCCESS;
/* Wake the target */ /* Wake the target */
DbgkpWakeTarget(DebugEvent); DbgkpWakeTarget(DebugEventToWake);
} }
else else
{ {
@ -1628,7 +1633,7 @@ NtDebugActiveProcess(IN HANDLE ProcessHandle,
{ {
PEPROCESS Process; PEPROCESS Process;
PDEBUG_OBJECT DebugObject; PDEBUG_OBJECT DebugObject;
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
PETHREAD LastThread; PETHREAD LastThread;
NTSTATUS Status; NTSTATUS Status;
PAGED_CODE(); PAGED_CODE();
@ -1644,8 +1649,9 @@ NtDebugActiveProcess(IN HANDLE ProcessHandle,
NULL); NULL);
if (!NT_SUCCESS(Status)) return Status; if (!NT_SUCCESS(Status)) return Status;
/* Don't allow debugging the initial system process */ /* Don't allow debugging the current process or the system process */
if (Process == PsInitialSystemProcess) if ((Process == PsGetCurrentProcess()) ||
(Process == PsInitialSystemProcess))
{ {
/* Dereference and fail */ /* Dereference and fail */
ObDereferenceObject(Process); ObDereferenceObject(Process);
@ -1700,7 +1706,7 @@ NtRemoveProcessDebug(IN HANDLE ProcessHandle,
{ {
PEPROCESS Process; PEPROCESS Process;
PDEBUG_OBJECT DebugObject; PDEBUG_OBJECT DebugObject;
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status; NTSTATUS Status;
PAGED_CODE(); PAGED_CODE();
DBGKTRACE(DBGK_PROCESS_DEBUG, "Process: %p Handle: %p\n", DBGKTRACE(DBGK_PROCESS_DEBUG, "Process: %p Handle: %p\n",
@ -1823,7 +1829,7 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
OUT PDBGUI_WAIT_STATE_CHANGE StateChange) OUT PDBGUI_WAIT_STATE_CHANGE StateChange)
{ {
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
LARGE_INTEGER SafeTimeOut; LARGE_INTEGER LocalTimeOut;
PEPROCESS Process; PEPROCESS Process;
LARGE_INTEGER StartTime; LARGE_INTEGER StartTime;
PETHREAD Thread; PETHREAD Thread;
@ -1837,44 +1843,46 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
PAGED_CODE(); PAGED_CODE();
DBGKTRACE(DBGK_OBJECT_DEBUG, "Handle: %p\n", DebugHandle); DBGKTRACE(DBGK_OBJECT_DEBUG, "Handle: %p\n", DebugHandle);
/* Clear the initial wait state change structure */ /* Clear the initial wait state change structure and the timeout */
RtlZeroMemory(&WaitStateChange, sizeof(WaitStateChange)); RtlZeroMemory(&WaitStateChange, sizeof(WaitStateChange));
LocalTimeOut.QuadPart = 0;
/* Protect probe in SEH */ /* Check if we were called from user mode */
_SEH2_TRY if (PreviousMode != KernelMode)
{ {
/* Check if we came with a timeout */ /* Protect probe in SEH */
if (Timeout) _SEH2_TRY
{ {
/* Check if the call was from user mode */ /* Check if we came with a timeout */
if (PreviousMode != KernelMode) if (Timeout)
{ {
/* Probe it */ /* Probe it */
ProbeForReadLargeInteger(Timeout); ProbeForReadLargeInteger(Timeout);
/* Make a local copy */
LocalTimeOut = *Timeout;
Timeout = &LocalTimeOut;
} }
/* Make a local copy */
SafeTimeOut = *Timeout;
Timeout = &SafeTimeOut;
/* Query the current time */
KeQuerySystemTime(&StartTime);
}
/* Check if the call was from user mode */
if (PreviousMode != KernelMode)
{
/* Probe the state change structure */ /* Probe the state change structure */
ProbeForWrite(StateChange, sizeof(*StateChange), sizeof(ULONG)); ProbeForWrite(StateChange, sizeof(*StateChange), sizeof(ULONG));
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Get the exception code */
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
if (!NT_SUCCESS(Status)) return Status;
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) else
{ {
/* Get the exception code */ /* Copy directly */
Status = _SEH2_GetExceptionCode(); if (Timeout) LocalTimeOut = *Timeout;
} }
_SEH2_END;
if (!NT_SUCCESS(Status)) return Status; /* If we were passed a timeout, query the current time */
if (Timeout) KeQuerySystemTime(&StartTime);
/* Get the debug object */ /* Get the debug object */
Status = ObReferenceObjectByHandle(DebugHandle, Status = ObReferenceObjectByHandle(DebugHandle,
@ -1892,7 +1900,7 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
/* Wait on the debug object given to us */ /* Wait on the debug object given to us */
while (TRUE) while (TRUE)
{ {
Status = KeWaitForSingleObject(DebugObject, Status = KeWaitForSingleObject(&DebugObject->EventsPresent,
Executive, Executive,
PreviousMode, PreviousMode,
Alertable, Alertable,
@ -2002,17 +2010,17 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
if (!GotEvent) if (!GotEvent)
{ {
/* Check if we can wait again */ /* Check if we can wait again */
if (SafeTimeOut.QuadPart < 0) if (LocalTimeOut.QuadPart < 0)
{ {
/* Query the new time */ /* Query the new time */
KeQuerySystemTime(&NewTime); KeQuerySystemTime(&NewTime);
/* Substract times */ /* Substract times */
SafeTimeOut.QuadPart += (NewTime.QuadPart - StartTime.QuadPart); LocalTimeOut.QuadPart += (NewTime.QuadPart - StartTime.QuadPart);
StartTime = NewTime; StartTime = NewTime;
/* Check if we've timed out */ /* Check if we've timed out */
if (SafeTimeOut.QuadPart >= 0) if (LocalTimeOut.QuadPart >= 0)
{ {
/* We have, break out of the loop */ /* We have, break out of the loop */
Status = STATUS_TIMEOUT; Status = STATUS_TIMEOUT;

View file

@ -12,8 +12,6 @@
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
extern ULONG DbgkpTraceLevel;
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
HANDLE HANDLE
@ -86,9 +84,9 @@ DbgkpResumeProcess(VOID)
VOID VOID
NTAPI NTAPI
DbgkCreateThread(PVOID StartAddress) DbgkCreateThread(IN PETHREAD Thread,
IN PVOID StartAddress)
{ {
PETHREAD Thread = PsGetCurrentThread();
PEPROCESS Process = PsGetCurrentProcess(); PEPROCESS Process = PsGetCurrentProcess();
ULONG ProcessFlags; ULONG ProcessFlags;
IMAGE_INFO ImageInfo; IMAGE_INFO ImageInfo;
@ -106,10 +104,13 @@ DbgkCreateThread(PVOID StartAddress)
PTEB Teb; PTEB Teb;
PAGED_CODE(); PAGED_CODE();
/* Sanity check */
ASSERT(Thread == PsGetCurrentThread());
/* Try ORing in the create reported and image notify flags */ /* Try ORing in the create reported and image notify flags */
ProcessFlags = InterlockedOr((PLONG)&Process->Flags, ProcessFlags = PspSetProcessFlag(Process,
PSF_CREATE_REPORTED_BIT | PSF_CREATE_REPORTED_BIT |
PSF_IMAGE_NOTIFY_DONE_BIT); PSF_IMAGE_NOTIFY_DONE_BIT);
/* Check if we were the first to set them or if another thread raced us */ /* Check if we were the first to set them or if another thread raced us */
if (!(ProcessFlags & PSF_IMAGE_NOTIFY_DONE_BIT) && (PsImageNotifyEnabled)) if (!(ProcessFlags & PSF_IMAGE_NOTIFY_DONE_BIT) && (PsImageNotifyEnabled))
@ -282,7 +283,7 @@ DbgkCreateThread(PVOID StartAddress)
{ {
/* Otherwise, do it just for the thread */ /* Otherwise, do it just for the thread */
CreateThread->SubSystemKey = 0; CreateThread->SubSystemKey = 0;
CreateThread->StartAddress = NULL; CreateThread->StartAddress = StartAddress;
/* Setup the API Message */ /* Setup the API Message */
ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 | ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 |
@ -385,11 +386,10 @@ DbgkMapViewOfSection(IN PVOID Section,
DBGKTRACE(DBGK_PROCESS_DEBUG, DBGKTRACE(DBGK_PROCESS_DEBUG,
"Section: %p. Base: %p\n", Section, BaseAddress); "Section: %p. Base: %p\n", Section, BaseAddress);
/* Check if this thread is hidden, doesn't have a debug port, or died */ /* Check if this thread is kernel, hidden or doesn't have a debug port */
if ((Thread->HideFromDebugger) || if ((ExGetPreviousMode() == KernelMode) ||
!(Process->DebugPort) || (Thread->HideFromDebugger) ||
(Thread->DeadThread) || !(Process->DebugPort))
(KeGetPreviousMode() == KernelMode))
{ {
/* Don't notify the debugger */ /* Don't notify the debugger */
return; return;
@ -434,11 +434,10 @@ DbgkUnMapViewOfSection(IN PVOID BaseAddress)
PETHREAD Thread = PsGetCurrentThread(); PETHREAD Thread = PsGetCurrentThread();
PAGED_CODE(); PAGED_CODE();
/* Check if this thread is hidden, doesn't have a debug port, or died */ /* Check if this thread is kernel, hidden or doesn't have a debug port */
if ((Thread->HideFromDebugger) || if ((ExGetPreviousMode() == KernelMode) ||
!(Process->DebugPort) || (Thread->HideFromDebugger) ||
(Thread->DeadThread) || !(Process->DebugPort))
(KeGetPreviousMode() == KernelMode))
{ {
/* Don't notify the debugger */ /* Don't notify the debugger */
return; return;
@ -456,5 +455,3 @@ DbgkUnMapViewOfSection(IN PVOID BaseAddress)
/* Send the message */ /* Send the message */
DbgkpSendApiMessage(&ApiMessage, TRUE); DbgkpSendApiMessage(&ApiMessage, TRUE);
} }
/* EOF */

View file

@ -56,6 +56,7 @@ DbgkInitialize(
VOID VOID
NTAPI NTAPI
DbgkCreateThread( DbgkCreateThread(
IN PETHREAD Thread,
IN PVOID StartAddress IN PVOID StartAddress
); );
@ -133,6 +134,7 @@ DbgkClearProcessDebugObject(
IN PDEBUG_OBJECT SourceDebugObject IN PDEBUG_OBJECT SourceDebugObject
); );
extern ULONG DbgkpTraceLevel;
extern POBJECT_TYPE DbgkDebugObjectType; extern POBJECT_TYPE DbgkDebugObjectType;
/* EOF */ /* EOF */

View file

@ -56,7 +56,7 @@ PspUserThreadStartup(IN PKSTART_ROUTINE StartRoutine,
if (!(Thread->DeadThread) && !(Thread->HideFromDebugger)) if (!(Thread->DeadThread) && !(Thread->HideFromDebugger))
{ {
/* We're not, so notify the debugger */ /* We're not, so notify the debugger */
DbgkCreateThread(StartContext); DbgkCreateThread(Thread, StartContext);
} }
/* Make sure we're not already dead */ /* Make sure we're not already dead */