Bug found by arty, thanks to alex for helping fix it:

Process termination fixes part 1: don't suicide our process when we're killing
a sibling.

 - Clarify the use of KillByHandle.  It does *not* mean "suicide".
 - In fact, we had considered the use of KillByHandle backward, that is,
   our process would commit suicide if it was killing a sibling process.
 - Make suicide contingent on killing the same process.
 - Properly handle DBG_TERMINATE_PROCESS semidocumented debugger hack.

svn path=/trunk/; revision=28451
This commit is contained in:
Art Yerkes 2007-08-22 07:28:45 +00:00
parent 2858198372
commit 01d8c61545
2 changed files with 30 additions and 19 deletions

View file

@ -58,6 +58,10 @@
#define PSREFTRACE(x)
#endif
#define PspSetProcessFlag(Process, Flag) \
InterlockedOr((PLONG)&Process->Flags, Flag)
//
// Maximum Count of Notification Routines
//

View file

@ -1108,12 +1108,21 @@ NtTerminateProcess(IN HANDLE ProcessHandle OPTIONAL,
PSTRACE(PS_KILL_DEBUG,
"ProcessHandle: %p ExitStatus: %p\n", ProcessHandle, ExitStatus);
/* Remember how we will kill it */
KillByHandle = (ProcessHandle != NULL);
/* Were we passed a process handle? */
if (ProcessHandle)
{
/* Yes we were, use it */
KillByHandle = TRUE;
}
else
{
/* We weren't... we assume this is suicide */
KillByHandle = FALSE;
ProcessHandle = NtCurrentProcess();
}
/* Get the Process Object */
Status = ObReferenceObjectByHandle((KillByHandle) ?
ProcessHandle : NtCurrentProcess(),
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_TERMINATE,
PsProcessType,
KeGetPreviousMode(),
@ -1138,9 +1147,8 @@ NtTerminateProcess(IN HANDLE ProcessHandle OPTIONAL,
return STATUS_PROCESS_IS_TERMINATING;
}
/* Set the delete flag */
if (!KillByHandle) InterlockedOr((PLONG)&Process->Flags,
PSF_PROCESS_DELETE_BIT);
/* Set the delete flag, unless the process is comitting suicide */
if (KillByHandle) PspSetProcessFlag(Process, PSF_PROCESS_DELETE_BIT);
/* Get the first thread */
Status = STATUS_NOTHING_TO_TERMINATE;
@ -1169,23 +1177,22 @@ NtTerminateProcess(IN HANDLE ProcessHandle OPTIONAL,
ExReleaseRundownProtection(&Process->RundownProtect);
/* Check if we are killing ourselves */
if (Process != CurrentProcess)
if (Process == CurrentProcess)
{
/* Check for the DBG_TERMINATE_PROCESS exit code */
if (ExitStatus == DBG_TERMINATE_PROCESS)
/* Also make sure the caller gave us our handle */
if (KillByHandle)
{
/* Disable debugging on this process */
DbgkClearProcessDebugObject(Process, NULL);
/* Dereference the project */
ObDereferenceObject(Process);
/* Terminate ourselves */
PspTerminateThreadByPointer(CurrentThread, ExitStatus, TRUE);
}
}
/* Make sure that we got a handle */
else if (KillByHandle)
else if (ExitStatus == DBG_TERMINATE_PROCESS)
{
/* Dereference the project */
ObDereferenceObject(Process);
/* Terminate ourselves */
PspTerminateThreadByPointer(CurrentThread, ExitStatus, TRUE);
/* Disable debugging on this process */
DbgkClearProcessDebugObject(Process, NULL);
}
/* Check if there was nothing to terminate, or if we have a Debug Port */