mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 09:25:10 +00:00
- 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:
parent
a0520cb3ae
commit
3c445f492d
4 changed files with 69 additions and 62 deletions
|
@ -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,37 +1843,30 @@ 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;
|
||||||
|
|
||||||
|
/* Check if we were called from user mode */
|
||||||
|
if (PreviousMode != KernelMode)
|
||||||
|
{
|
||||||
/* Protect probe in SEH */
|
/* Protect probe in SEH */
|
||||||
_SEH2_TRY
|
_SEH2_TRY
|
||||||
{
|
{
|
||||||
/* Check if we came with a timeout */
|
/* Check if we came with a timeout */
|
||||||
if (Timeout)
|
if (Timeout)
|
||||||
{
|
|
||||||
/* Check if the call was from user mode */
|
|
||||||
if (PreviousMode != KernelMode)
|
|
||||||
{
|
{
|
||||||
/* Probe it */
|
/* Probe it */
|
||||||
ProbeForReadLargeInteger(Timeout);
|
ProbeForReadLargeInteger(Timeout);
|
||||||
}
|
|
||||||
|
|
||||||
/* Make a local copy */
|
/* Make a local copy */
|
||||||
SafeTimeOut = *Timeout;
|
LocalTimeOut = *Timeout;
|
||||||
Timeout = &SafeTimeOut;
|
Timeout = &LocalTimeOut;
|
||||||
|
|
||||||
/* 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)
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
{
|
{
|
||||||
/* Get the exception code */
|
/* Get the exception code */
|
||||||
|
@ -1875,6 +1874,15 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle,
|
||||||
}
|
}
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
if (!NT_SUCCESS(Status)) return Status;
|
if (!NT_SUCCESS(Status)) return Status;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Copy directly */
|
||||||
|
if (Timeout) LocalTimeOut = *Timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
|
@ -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,8 +104,11 @@ 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);
|
||||||
|
|
||||||
|
@ -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 */
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in a new issue