From 3c445f492d411cf11276e272d252cb66a2a50a4d Mon Sep 17 00:00:00 2001 From: Stefan Ginsberg Date: Thu, 15 Jan 2009 13:14:37 +0000 Subject: [PATCH] - 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 --- reactos/ntoskrnl/dbgk/dbgkobj.c | 90 +++++++++++++----------- reactos/ntoskrnl/dbgk/dbgkutil.c | 37 +++++----- reactos/ntoskrnl/include/internal/dbgk.h | 2 + reactos/ntoskrnl/ps/thread.c | 2 +- 4 files changed, 69 insertions(+), 62 deletions(-) diff --git a/reactos/ntoskrnl/dbgk/dbgkobj.c b/reactos/ntoskrnl/dbgk/dbgkobj.c index 99961a585c7..3a6032e16aa 100644 --- a/reactos/ntoskrnl/dbgk/dbgkobj.c +++ b/reactos/ntoskrnl/dbgk/dbgkobj.c @@ -219,7 +219,7 @@ DbgkpSendApiMessageLpc(IN OUT PDBGKM_MSG Message, Message->ReturnedStatus = STATUS_PENDING; /* Set create process reported state */ - PsGetCurrentProcess()->CreateReported = TRUE; + PspSetProcessFlag(PsGetCurrentProcess(), PSF_CREATE_REPORTED_BIT); /* Send the LPC command */ Status = LpcRequestWaitReplyPort(Port, @@ -254,7 +254,7 @@ DbgkpSendApiMessage(IN OUT PDBGKM_MSG ApiMsg, ApiMsg->ReturnedStatus = STATUS_PENDING; /* Set create process reported state */ - PsGetCurrentProcess()->CreateReported = TRUE; + PspSetProcessFlag(PsGetCurrentProcess(), PSF_CREATE_REPORTED_BIT); /* Send the LPC command */ Status = DbgkpQueueMessage(PsGetCurrentProcess(), @@ -1081,6 +1081,7 @@ DbgkpCloseObject(IN PEPROCESS OwnerProcess OPTIONAL, BOOLEAN DebugPortCleared = FALSE; PLIST_ENTRY DebugEventList; PDEBUG_EVENT DebugEvent; + PAGED_CODE(); DBGKTRACE(DBGK_OBJECT_DEBUG, "OwnerProcess: %p DebugObject: %p\n", OwnerProcess, DebugObject); @@ -1260,8 +1261,9 @@ ThreadScan: else { /* Set the process flags */ - InterlockedOr((PLONG)&Process->Flags, - PSF_NO_DEBUG_INHERIT_BIT | PSF_CREATE_REPORTED_BIT); + PspSetProcessFlag(Process, + PSF_NO_DEBUG_INHERIT_BIT | + PSF_CREATE_REPORTED_BIT); /* Reference the debug object */ ObReferenceObject(DebugObject); @@ -1474,12 +1476,15 @@ NtCreateDebugObject(OUT PHANDLE DebugHandle, &hDebug); if (NT_SUCCESS(Status)) { + /* Enter SEH to protect the write */ _SEH2_TRY { + /* Return the handle */ *DebugHandle = hDebug; } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + _SEH2_EXCEPT(ExSystemExceptionFilter()) { + /* Get the exception code */ Status = _SEH2_GetExceptionCode(); } _SEH2_END; } @@ -1570,7 +1575,7 @@ NtDebugContinue(IN HANDLE DebugHandle, { /* Wake it up and break out */ DebugEvent->Flags &= ~DEBUG_EVENT_INACTIVE; - KeSetEvent(&DebugEvent->ContinueEvent, + KeSetEvent(&DebugObject->EventsPresent, IO_NO_INCREMENT, FALSE); break; @@ -1603,11 +1608,11 @@ NtDebugContinue(IN HANDLE DebugHandle, if (NeedsWake) { /* Set the continue status */ - DebugEvent->ApiMsg.ReturnedStatus = ContinueStatus; - DebugEvent->Status = STATUS_SUCCESS; + DebugEventToWake->ApiMsg.ReturnedStatus = ContinueStatus; + DebugEventToWake->Status = STATUS_SUCCESS; /* Wake the target */ - DbgkpWakeTarget(DebugEvent); + DbgkpWakeTarget(DebugEventToWake); } else { @@ -1628,7 +1633,7 @@ NtDebugActiveProcess(IN HANDLE ProcessHandle, { PEPROCESS Process; PDEBUG_OBJECT DebugObject; - KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); PETHREAD LastThread; NTSTATUS Status; PAGED_CODE(); @@ -1644,8 +1649,9 @@ NtDebugActiveProcess(IN HANDLE ProcessHandle, NULL); if (!NT_SUCCESS(Status)) return Status; - /* Don't allow debugging the initial system process */ - if (Process == PsInitialSystemProcess) + /* Don't allow debugging the current process or the system process */ + if ((Process == PsGetCurrentProcess()) || + (Process == PsInitialSystemProcess)) { /* Dereference and fail */ ObDereferenceObject(Process); @@ -1700,7 +1706,7 @@ NtRemoveProcessDebug(IN HANDLE ProcessHandle, { PEPROCESS Process; PDEBUG_OBJECT DebugObject; - KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); NTSTATUS Status; PAGED_CODE(); DBGKTRACE(DBGK_PROCESS_DEBUG, "Process: %p Handle: %p\n", @@ -1823,7 +1829,7 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle, OUT PDBGUI_WAIT_STATE_CHANGE StateChange) { KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); - LARGE_INTEGER SafeTimeOut; + LARGE_INTEGER LocalTimeOut; PEPROCESS Process; LARGE_INTEGER StartTime; PETHREAD Thread; @@ -1837,44 +1843,46 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle, PAGED_CODE(); 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)); + LocalTimeOut.QuadPart = 0; - /* Protect probe in SEH */ - _SEH2_TRY + /* Check if we were called from user mode */ + if (PreviousMode != KernelMode) { - /* Check if we came with a timeout */ - if (Timeout) + /* Protect probe in SEH */ + _SEH2_TRY { - /* Check if the call was from user mode */ - if (PreviousMode != KernelMode) + /* Check if we came with a timeout */ + if (Timeout) { /* Probe it */ ProbeForReadLargeInteger(Timeout); - } - - /* Make a local copy */ - SafeTimeOut = *Timeout; - Timeout = &SafeTimeOut; - /* Query the current time */ - KeQuerySystemTime(&StartTime); - } + /* Make a local copy */ + LocalTimeOut = *Timeout; + Timeout = &LocalTimeOut; + } - /* Check if the call was from user mode */ - if (PreviousMode != KernelMode) - { /* Probe the state change structure */ 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 */ - Status = _SEH2_GetExceptionCode(); + /* Copy directly */ + 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 */ Status = ObReferenceObjectByHandle(DebugHandle, @@ -1892,7 +1900,7 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle, /* Wait on the debug object given to us */ while (TRUE) { - Status = KeWaitForSingleObject(DebugObject, + Status = KeWaitForSingleObject(&DebugObject->EventsPresent, Executive, PreviousMode, Alertable, @@ -2002,17 +2010,17 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle, if (!GotEvent) { /* Check if we can wait again */ - if (SafeTimeOut.QuadPart < 0) + if (LocalTimeOut.QuadPart < 0) { /* Query the new time */ KeQuerySystemTime(&NewTime); /* Substract times */ - SafeTimeOut.QuadPart += (NewTime.QuadPart - StartTime.QuadPart); + LocalTimeOut.QuadPart += (NewTime.QuadPart - StartTime.QuadPart); StartTime = NewTime; /* Check if we've timed out */ - if (SafeTimeOut.QuadPart >= 0) + if (LocalTimeOut.QuadPart >= 0) { /* We have, break out of the loop */ Status = STATUS_TIMEOUT; diff --git a/reactos/ntoskrnl/dbgk/dbgkutil.c b/reactos/ntoskrnl/dbgk/dbgkutil.c index 1cd0749b330..2285c95a955 100644 --- a/reactos/ntoskrnl/dbgk/dbgkutil.c +++ b/reactos/ntoskrnl/dbgk/dbgkutil.c @@ -12,8 +12,6 @@ #define NDEBUG #include -extern ULONG DbgkpTraceLevel; - /* FUNCTIONS *****************************************************************/ HANDLE @@ -86,9 +84,9 @@ DbgkpResumeProcess(VOID) VOID NTAPI -DbgkCreateThread(PVOID StartAddress) +DbgkCreateThread(IN PETHREAD Thread, + IN PVOID StartAddress) { - PETHREAD Thread = PsGetCurrentThread(); PEPROCESS Process = PsGetCurrentProcess(); ULONG ProcessFlags; IMAGE_INFO ImageInfo; @@ -106,10 +104,13 @@ DbgkCreateThread(PVOID StartAddress) PTEB Teb; PAGED_CODE(); + /* Sanity check */ + ASSERT(Thread == PsGetCurrentThread()); + /* Try ORing in the create reported and image notify flags */ - ProcessFlags = InterlockedOr((PLONG)&Process->Flags, - PSF_CREATE_REPORTED_BIT | - PSF_IMAGE_NOTIFY_DONE_BIT); + ProcessFlags = PspSetProcessFlag(Process, + PSF_CREATE_REPORTED_BIT | + PSF_IMAGE_NOTIFY_DONE_BIT); /* Check if we were the first to set them or if another thread raced us */ if (!(ProcessFlags & PSF_IMAGE_NOTIFY_DONE_BIT) && (PsImageNotifyEnabled)) @@ -282,7 +283,7 @@ DbgkCreateThread(PVOID StartAddress) { /* Otherwise, do it just for the thread */ CreateThread->SubSystemKey = 0; - CreateThread->StartAddress = NULL; + CreateThread->StartAddress = StartAddress; /* Setup the API Message */ ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 | @@ -385,11 +386,10 @@ DbgkMapViewOfSection(IN PVOID Section, DBGKTRACE(DBGK_PROCESS_DEBUG, "Section: %p. Base: %p\n", Section, BaseAddress); - /* Check if this thread is hidden, doesn't have a debug port, or died */ - if ((Thread->HideFromDebugger) || - !(Process->DebugPort) || - (Thread->DeadThread) || - (KeGetPreviousMode() == KernelMode)) + /* Check if this thread is kernel, hidden or doesn't have a debug port */ + if ((ExGetPreviousMode() == KernelMode) || + (Thread->HideFromDebugger) || + !(Process->DebugPort)) { /* Don't notify the debugger */ return; @@ -434,11 +434,10 @@ DbgkUnMapViewOfSection(IN PVOID BaseAddress) PETHREAD Thread = PsGetCurrentThread(); PAGED_CODE(); - /* Check if this thread is hidden, doesn't have a debug port, or died */ - if ((Thread->HideFromDebugger) || - !(Process->DebugPort) || - (Thread->DeadThread) || - (KeGetPreviousMode() == KernelMode)) + /* Check if this thread is kernel, hidden or doesn't have a debug port */ + if ((ExGetPreviousMode() == KernelMode) || + (Thread->HideFromDebugger) || + !(Process->DebugPort)) { /* Don't notify the debugger */ return; @@ -456,5 +455,3 @@ DbgkUnMapViewOfSection(IN PVOID BaseAddress) /* Send the message */ DbgkpSendApiMessage(&ApiMessage, TRUE); } - -/* EOF */ diff --git a/reactos/ntoskrnl/include/internal/dbgk.h b/reactos/ntoskrnl/include/internal/dbgk.h index 975272916cb..47c28429b86 100644 --- a/reactos/ntoskrnl/include/internal/dbgk.h +++ b/reactos/ntoskrnl/include/internal/dbgk.h @@ -56,6 +56,7 @@ DbgkInitialize( VOID NTAPI DbgkCreateThread( + IN PETHREAD Thread, IN PVOID StartAddress ); @@ -133,6 +134,7 @@ DbgkClearProcessDebugObject( IN PDEBUG_OBJECT SourceDebugObject ); +extern ULONG DbgkpTraceLevel; extern POBJECT_TYPE DbgkDebugObjectType; /* EOF */ diff --git a/reactos/ntoskrnl/ps/thread.c b/reactos/ntoskrnl/ps/thread.c index 068d383764d..3ed792e7447 100644 --- a/reactos/ntoskrnl/ps/thread.c +++ b/reactos/ntoskrnl/ps/thread.c @@ -56,7 +56,7 @@ PspUserThreadStartup(IN PKSTART_ROUTINE StartRoutine, if (!(Thread->DeadThread) && !(Thread->HideFromDebugger)) { /* We're not, so notify the debugger */ - DbgkCreateThread(StartContext); + DbgkCreateThread(Thread, StartContext); } /* Make sure we're not already dead */ -- 2.17.1