mirror of
https://github.com/reactos/reactos.git
synced 2024-06-26 07:51:52 +00:00
[25 bug fixes]:
- Implement KeReadStateThread. - Fix PspTerminateProcess to handle case where there's no threads in the process. - Fix check in PspTerminateProcess. ObClearProcessHandleTable gets called if there's a debug port, not if there's an object table. - Simplfy PspReapRoutine. - Fix PspExitThread to wait for all other threads before continuing to kill the last thread. Should fix lots of race/wait conditions. - PspExitThread should check for !DeadThread and not !Terminated before determining if it should free the TEB. Also, the DbgK handle should only be closed if the thread isn't already dead. - Fixup formatting of some code to warn less on MSVC. - Fail various APIs if acquiring rundown protection failed. - Fix Process Quantum/Priority settings. - Grant PROCESS_TERMINATE by default. - Add PROCESS_SET_INFORMATION, STANDARD_RIGHTS_ALL and PROCESS_SET_QUOTA to the default process granted access mask. - Initialize process/thread/image notification callbacks durin phase 0 Ps initialization. - The Audit Name belongs to the system process, not the idle process. - Detect more failures in phase 0 startup. - Fix various race conditions/incorrect checks in ps/security.c related to impersonation information. Also allow PspAssignPrimaryToken to be called directly with the token pointer and not only the handle. - Wrap system thread startup stub in SEH and write a SEH filter function to print out debug information when a system thread dies unexpectedly. svn path=/trunk/; revision=25504
This commit is contained in:
parent
ccee43a360
commit
9522e0a02b
|
@ -215,6 +215,10 @@ NTSTATUS
|
|||
NTAPI
|
||||
KeSuspendThread(PKTHREAD Thread);
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
KeReadStateThread(IN PKTHREAD Thread);
|
||||
|
||||
BOOLEAN
|
||||
FASTCALL
|
||||
KiSwapContext(
|
||||
|
|
|
@ -93,7 +93,8 @@ VOID
|
|||
NTAPI
|
||||
LpcpSaveDataInfoMessage(
|
||||
IN PLPCP_PORT_OBJECT Port,
|
||||
IN PLPCP_MESSAGE Message
|
||||
IN PLPCP_MESSAGE Message,
|
||||
IN ULONG LockHeld
|
||||
);
|
||||
|
||||
//
|
||||
|
|
|
@ -175,7 +175,7 @@ NTAPI
|
|||
PspSetPrimaryToken(
|
||||
IN PEPROCESS Process,
|
||||
IN HANDLE TokenHandle OPTIONAL,
|
||||
IN PTOKEN Token OPTIONAL
|
||||
IN PACCESS_TOKEN Token OPTIONAL
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
|
|
|
@ -46,6 +46,17 @@ KeFindNextRightSetAffinity(IN UCHAR Number,
|
|||
return (UCHAR)Result;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
KeReadStateThread(IN PKTHREAD Thread)
|
||||
{
|
||||
ASSERT_THREAD(Thread);
|
||||
|
||||
/* Return signal state */
|
||||
return (BOOLEAN)Thread->DispatcherHeader.SignalState;
|
||||
}
|
||||
|
||||
KPRIORITY
|
||||
NTAPI
|
||||
KeQueryBasePriorityThread(IN PKTHREAD Thread)
|
||||
|
|
|
@ -57,7 +57,8 @@ LpcpFreeDataInfoMessage(IN PLPCP_PORT_OBJECT Port,
|
|||
VOID
|
||||
NTAPI
|
||||
LpcpSaveDataInfoMessage(IN PLPCP_PORT_OBJECT Port,
|
||||
IN PLPCP_MESSAGE Message)
|
||||
IN PLPCP_MESSAGE Message,
|
||||
IN ULONG LockFlags)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
|
@ -402,7 +403,7 @@ NtReplyWaitReceivePortEx(IN HANDLE PortHandle,
|
|||
if (Message->Request.u2.s2.DataInfoOffset)
|
||||
{
|
||||
/* It does, save it, and don't free the message below */
|
||||
LpcpSaveDataInfoMessage(Port, Message);
|
||||
LpcpSaveDataInfoMessage(Port, Message, 1);
|
||||
Message = NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -391,7 +391,7 @@ NtRequestWaitReplyPort(IN HANDLE PortHandle,
|
|||
(Message->Request.u2.s2.DataInfoOffset))
|
||||
{
|
||||
/* Save the data information */
|
||||
LpcpSaveDataInfoMessage(Port, Message);
|
||||
LpcpSaveDataInfoMessage(Port, Message, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
LIST_ENTRY PspReaperListHead = {0};
|
||||
WORK_QUEUE_ITEM PspReaperWorkItem;
|
||||
LARGE_INTEGER ShortTime = {{-10 * 100 * 1000, -1}};
|
||||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
|
@ -81,7 +82,8 @@ NTAPI
|
|||
PspTerminateProcess(IN PEPROCESS Process,
|
||||
IN NTSTATUS ExitStatus)
|
||||
{
|
||||
PETHREAD Thread = NULL;
|
||||
PETHREAD Thread;
|
||||
NTSTATUS Status = STATUS_NOTHING_TO_TERMINATE;
|
||||
PAGED_CODE();
|
||||
PSTRACE(PS_KILL_DEBUG,
|
||||
"Process: %p ExitStatus: %p\n", Process, ExitStatus);
|
||||
|
@ -100,22 +102,26 @@ PspTerminateProcess(IN PEPROCESS Process,
|
|||
InterlockedOr((PLONG)&Process->Flags, PSF_PROCESS_DELETE_BIT);
|
||||
|
||||
/* Get the first thread */
|
||||
Thread = PsGetNextProcessThread(Process, Thread);
|
||||
Thread = PsGetNextProcessThread(Process, NULL);
|
||||
while (Thread)
|
||||
{
|
||||
/* Kill it */
|
||||
PSREFTRACE(Thread);
|
||||
PspTerminateThreadByPointer(Thread, ExitStatus, FALSE);
|
||||
PSREFTRACE(Thread);
|
||||
Thread = PsGetNextProcessThread(Process, Thread);
|
||||
|
||||
/* We had at least one thread, so termination is OK */
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Clear the handle table */
|
||||
if (Process->ObjectTable) ObClearProcessHandleTable(Process);
|
||||
/* Check if there was nothing to terminate or if we have a debug port */
|
||||
if ((Status == STATUS_NOTHING_TO_TERMINATE) || (Process->DebugPort))
|
||||
{
|
||||
/* Clear the handle table anyway */
|
||||
ObClearProcessHandleTable(Process);
|
||||
}
|
||||
|
||||
/* Return success*/
|
||||
PSREFTRACE(Process);
|
||||
return STATUS_SUCCESS;
|
||||
/* Return status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
|
@ -163,19 +169,16 @@ VOID
|
|||
NTAPI
|
||||
PspReapRoutine(IN PVOID Context)
|
||||
{
|
||||
PLIST_ENTRY *ListAddr;
|
||||
PLIST_ENTRY NextEntry;
|
||||
PSINGLE_LIST_ENTRY NextEntry;
|
||||
PETHREAD Thread;
|
||||
PSTRACE(PS_KILL_DEBUG, "Context: %p\n", Context);
|
||||
|
||||
/* Get the Reaper Address Pointer */
|
||||
ListAddr = &PspReaperListHead.Flink;
|
||||
|
||||
/* Start main loop */
|
||||
do
|
||||
{
|
||||
/* Write magic value and return the next entry to process */
|
||||
NextEntry = InterlockedExchangePointer(ListAddr, (PVOID)1);
|
||||
NextEntry = InterlockedExchangePointer(&PspReaperListHead.Flink,
|
||||
(PVOID)1);
|
||||
ASSERT((NextEntry != NULL) && (NextEntry != (PVOID)1));
|
||||
|
||||
/* Start inner loop */
|
||||
|
@ -190,15 +193,16 @@ PspReapRoutine(IN PVOID Context)
|
|||
Thread->Tcb.InitialStack = NULL;
|
||||
|
||||
/* Move to the next entry */
|
||||
NextEntry = NextEntry->Flink;
|
||||
NextEntry = NextEntry->Next;
|
||||
|
||||
/* Dereference this thread */
|
||||
ObDereferenceObject(Thread);
|
||||
PSREFTRACE(Thread);
|
||||
} while ((NextEntry != NULL) && (NextEntry != (PVOID)1));
|
||||
|
||||
/* Remove magic value, keep looping if it got changed */
|
||||
} while (InterlockedCompareExchangePointer(ListAddr, 0, 1) != (PVOID)1);
|
||||
} while (InterlockedCompareExchangePointer(&PspReaperListHead.Flink,
|
||||
0,
|
||||
1) != (PVOID)1);
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -245,7 +249,7 @@ PspDeleteProcess(IN PVOID ObjectBody)
|
|||
/* Check if we have a debug port */
|
||||
if (Process->DebugPort)
|
||||
{
|
||||
/* Dererence the Debug Port */
|
||||
/* Deference the Debug Port */
|
||||
ObDereferenceObject(Process->DebugPort);
|
||||
Process->DebugPort = NULL;
|
||||
}
|
||||
|
@ -253,7 +257,7 @@ PspDeleteProcess(IN PVOID ObjectBody)
|
|||
/* Check if we have an exception port */
|
||||
if (Process->ExceptionPort)
|
||||
{
|
||||
/* Dererence the Exception Port */
|
||||
/* Deference the Exception Port */
|
||||
ObDereferenceObject(Process->ExceptionPort);
|
||||
Process->ExceptionPort = NULL;
|
||||
}
|
||||
|
@ -261,7 +265,7 @@ PspDeleteProcess(IN PVOID ObjectBody)
|
|||
/* Check if we have a section object */
|
||||
if (Process->SectionObject)
|
||||
{
|
||||
/* Dererence the Section Object */
|
||||
/* Deference the Section Object */
|
||||
ObDereferenceObject(Process->SectionObject);
|
||||
Process->SectionObject = NULL;
|
||||
}
|
||||
|
@ -279,7 +283,7 @@ PspDeleteProcess(IN PVOID ObjectBody)
|
|||
/* Kill the Object Info */
|
||||
ObKillProcess(Process);
|
||||
|
||||
/* Dettach */
|
||||
/* Detach */
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
}
|
||||
|
||||
|
@ -295,7 +299,7 @@ PspDeleteProcess(IN PVOID ObjectBody)
|
|||
/* Clean the Address Space */
|
||||
PspExitProcess(FALSE, Process);
|
||||
|
||||
/* Dettach */
|
||||
/* Detach */
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
|
||||
/* Completely delete the Address Space */
|
||||
|
@ -303,7 +307,7 @@ PspDeleteProcess(IN PVOID ObjectBody)
|
|||
}
|
||||
|
||||
/* See if we have a PID */
|
||||
if(Process->UniqueProcessId)
|
||||
if (Process->UniqueProcessId)
|
||||
{
|
||||
/* Delete the PID */
|
||||
if (!(ExDestroyHandle(PspCidTable, Process->UniqueProcessId)))
|
||||
|
@ -331,7 +335,6 @@ PspDeleteProcess(IN PVOID ObjectBody)
|
|||
|
||||
/* Destroy the Quota Block */
|
||||
PspDestroyQuotaBlock(Process);
|
||||
PSREFTRACE(Process);
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -368,7 +371,6 @@ PspDeleteThread(IN PVOID ObjectBody)
|
|||
PspDeleteThreadSecurity(Thread);
|
||||
|
||||
/* Make sure the thread was inserted, before continuing */
|
||||
PSREFTRACE(Thread);
|
||||
if (!Process) return;
|
||||
|
||||
/* Check if the thread list is valid */
|
||||
|
@ -388,8 +390,6 @@ PspDeleteThread(IN PVOID ObjectBody)
|
|||
|
||||
/* Dereference the Process */
|
||||
ObDereferenceObject(Process);
|
||||
PSREFTRACE(Thread);
|
||||
PSREFTRACE(Process);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -404,7 +404,7 @@ PspExitThread(IN NTSTATUS ExitStatus)
|
|||
NTSTATUS Status;
|
||||
PTEB Teb;
|
||||
PEPROCESS CurrentProcess;
|
||||
PETHREAD Thread;
|
||||
PETHREAD Thread, OtherThread, PreviousThread = NULL;
|
||||
PVOID DeallocationStack;
|
||||
ULONG Dummy;
|
||||
BOOLEAN Last = FALSE;
|
||||
|
@ -421,8 +421,6 @@ PspExitThread(IN NTSTATUS ExitStatus)
|
|||
ASSERT((Thread) == PsGetCurrentThread());
|
||||
|
||||
/* Can't terminate a thread if it attached another process */
|
||||
PSREFTRACE(Thread);
|
||||
PSREFTRACE(CurrentProcess);
|
||||
if (KeIsAttachedProcess())
|
||||
{
|
||||
/* Bugcheck */
|
||||
|
@ -434,7 +432,7 @@ PspExitThread(IN NTSTATUS ExitStatus)
|
|||
}
|
||||
|
||||
/* Lower to Passive Level */
|
||||
KfLowerIrql(PASSIVE_LEVEL);
|
||||
KeLowerIrql(PASSIVE_LEVEL);
|
||||
|
||||
/* Can't be a worker thread */
|
||||
if (Thread->ActiveExWorker)
|
||||
|
@ -453,9 +451,9 @@ PspExitThread(IN NTSTATUS ExitStatus)
|
|||
/* Bugcheck */
|
||||
KEBUGCHECKEX(KERNEL_APC_PENDING_DURING_EXIT,
|
||||
0,
|
||||
Thread->Tcb.KernelApcDisable,
|
||||
APC_LEVEL,
|
||||
0);
|
||||
Thread->Tcb.CombinedApcDisable,
|
||||
0,
|
||||
1);
|
||||
}
|
||||
|
||||
/* Lock the thread */
|
||||
|
@ -500,7 +498,44 @@ PspExitThread(IN NTSTATUS ExitStatus)
|
|||
CurrentProcess->ExitStatus = ExitStatus;
|
||||
}
|
||||
|
||||
/* FIXME: Wait on the other threads to finish */
|
||||
/* Loop all the current threads */
|
||||
FirstEntry = &CurrentProcess->ThreadListHead;
|
||||
CurrentEntry = FirstEntry->Flink;
|
||||
while (FirstEntry != CurrentEntry)
|
||||
{
|
||||
/* Get the thread on the list */
|
||||
OtherThread = CONTAINING_RECORD(CurrentEntry,
|
||||
ETHREAD,
|
||||
ThreadListEntry);
|
||||
|
||||
/* Check if it's a thread that's still alive */
|
||||
if ((OtherThread != Thread) &&
|
||||
!(KeReadStateThread(&OtherThread->Tcb)) &&
|
||||
(ObReferenceObjectSafe(OtherThread)))
|
||||
{
|
||||
/* It's a live thread and we referenced it, unlock process */
|
||||
ExReleasePushLockExclusive(&CurrentProcess->ProcessLock);
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
/* Wait on the thread */
|
||||
KeWaitForSingleObject(OtherThread,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
|
||||
/* Check if we had a previous thread to dereference */
|
||||
if (PreviousThread) ObDereferenceObject(PreviousThread);
|
||||
|
||||
/* Remember the thread and re-lock the process */
|
||||
PreviousThread = OtherThread;
|
||||
KeEnterCriticalRegion();
|
||||
ExAcquirePushLockExclusive(&CurrentProcess->ProcessLock);
|
||||
}
|
||||
|
||||
/* Go to the next thread */
|
||||
CurrentEntry = CurrentEntry->Flink;
|
||||
}
|
||||
}
|
||||
else if (ExitStatus != STATUS_THREAD_IS_TERMINATING)
|
||||
{
|
||||
|
@ -512,6 +547,9 @@ PspExitThread(IN NTSTATUS ExitStatus)
|
|||
ExReleasePushLockExclusive(&CurrentProcess->ProcessLock);
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
/* Check if we had a previous thread to dereference */
|
||||
if (PreviousThread) ObDereferenceObject(PreviousThread);
|
||||
|
||||
/* Check if the process has a debug port and if this is a user thread */
|
||||
if ((CurrentProcess->DebugPort) && !(Thread->SystemThread))
|
||||
{
|
||||
|
@ -570,15 +608,20 @@ PspExitThread(IN NTSTATUS ExitStatus)
|
|||
/* Save the Create Time */
|
||||
TerminationMsg.CreateTime = Thread->CreateTime;
|
||||
|
||||
TryAgain:
|
||||
/* Send the LPC Message */
|
||||
Status = LpcRequestPort(TerminationPort->Port, &TerminationMsg.h);
|
||||
if ((Status == STATUS_NO_MEMORY) ||
|
||||
(Status == STATUS_INSUFFICIENT_RESOURCES))
|
||||
/* Loop trying to send message */
|
||||
while (TRUE)
|
||||
{
|
||||
/* Wait a bit and try again */
|
||||
KeDelayExecutionThread(KernelMode, FALSE, &ShortPsLockDelay);
|
||||
goto TryAgain;
|
||||
/* Send the LPC Message */
|
||||
Status = LpcRequestPort(TerminationPort->Port,
|
||||
&TerminationMsg.h);
|
||||
if ((Status == STATUS_NO_MEMORY) ||
|
||||
(Status == STATUS_INSUFFICIENT_RESOURCES))
|
||||
{
|
||||
/* Wait a bit and try again */
|
||||
KeDelayExecutionThread(KernelMode, FALSE, &ShortTime);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Dereference this LPC Port */
|
||||
|
@ -591,7 +634,8 @@ TryAgain:
|
|||
ExFreePool(TerminationPort);
|
||||
|
||||
/* Keep looping as long as there is a port */
|
||||
} while ((TerminationPort = NextPort));
|
||||
TerminationPort = NextPort;
|
||||
} while (TerminationPort);
|
||||
}
|
||||
else if (((ExitStatus == STATUS_THREAD_IS_TERMINATING) &&
|
||||
(Thread->DeadThread)) ||
|
||||
|
@ -627,16 +671,20 @@ TryAgain:
|
|||
/* Save the Create Time */
|
||||
TerminationMsg.CreateTime = Thread->CreateTime;
|
||||
|
||||
TryAgain2:
|
||||
/* Send the LPC Message */
|
||||
Status = LpcRequestPort(CurrentProcess->ExceptionPort,
|
||||
&TerminationMsg.h);
|
||||
if ((Status == STATUS_NO_MEMORY) ||
|
||||
(Status == STATUS_INSUFFICIENT_RESOURCES))
|
||||
/* Loop trying to send message */
|
||||
while (TRUE)
|
||||
{
|
||||
/* Wait a bit and try again */
|
||||
KeDelayExecutionThread(KernelMode, FALSE, &ShortPsLockDelay);
|
||||
goto TryAgain2;
|
||||
/* Send the LPC Message */
|
||||
Status = LpcRequestPort(CurrentProcess->ExceptionPort,
|
||||
&TerminationMsg.h);
|
||||
if ((Status == STATUS_NO_MEMORY) ||
|
||||
(Status == STATUS_INSUFFICIENT_RESOURCES))
|
||||
{
|
||||
/* Wait a bit and try again */
|
||||
KeDelayExecutionThread(KernelMode, FALSE, &ShortTime);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -646,7 +694,6 @@ TryAgain2:
|
|||
PsW32ThreadCalloutExit);
|
||||
|
||||
/* If we are the last thread and have a W32 Process */
|
||||
PSREFTRACE(Thread);
|
||||
if ((Last) && (CurrentProcess->Win32Process))
|
||||
{
|
||||
/* Run it down too */
|
||||
|
@ -674,26 +721,30 @@ TryAgain2:
|
|||
|
||||
/* Check if we have a TEB */
|
||||
Teb = Thread->Tcb.Teb;
|
||||
if(Teb)
|
||||
if (Teb)
|
||||
{
|
||||
/* Check if the thread isn't terminated and if we should free stack */
|
||||
if (!(Thread->Terminated) && (Teb->FreeStackOnTermination))
|
||||
/* Check if the thread is still alive */
|
||||
if (!Thread->DeadThread)
|
||||
{
|
||||
/* Set the TEB's Deallocation Stack as the Base Address */
|
||||
Dummy = 0;
|
||||
DeallocationStack = Teb->DeallocationStack;
|
||||
/* Check if we need to free its stack */
|
||||
if (Teb->FreeStackOnTermination)
|
||||
{
|
||||
/* Set the TEB's Deallocation Stack as the Base Address */
|
||||
Dummy = 0;
|
||||
DeallocationStack = Teb->DeallocationStack;
|
||||
|
||||
/* Free the Thread's Stack */
|
||||
ZwFreeVirtualMemory(NtCurrentProcess(),
|
||||
&DeallocationStack,
|
||||
&Dummy,
|
||||
MEM_RELEASE);
|
||||
/* Free the Thread's Stack */
|
||||
ZwFreeVirtualMemory(NtCurrentProcess(),
|
||||
&DeallocationStack,
|
||||
&Dummy,
|
||||
MEM_RELEASE);
|
||||
}
|
||||
|
||||
/* Free the debug handle */
|
||||
if (Teb->DbgSsReserved[1]) ObCloseHandle(Teb->DbgSsReserved[1],
|
||||
UserMode);
|
||||
}
|
||||
|
||||
/* Free the debug handle */
|
||||
if (Teb->DbgSsReserved[1]) ObCloseHandle(Teb->DbgSsReserved[1],
|
||||
UserMode);
|
||||
|
||||
/* Decommit the TEB */
|
||||
MmDeleteTeb(CurrentProcess, Teb);
|
||||
Thread->Tcb.Teb = NULL;
|
||||
|
@ -710,8 +761,6 @@ TryAgain2:
|
|||
ASSERT(Thread->Tcb.CombinedApcDisable == 0);
|
||||
|
||||
/* Check if this is the final thread or not */
|
||||
PSREFTRACE(Thread);
|
||||
PSREFTRACE(CurrentProcess);
|
||||
if (Last)
|
||||
{
|
||||
/* Set the process exit time */
|
||||
|
@ -736,7 +785,6 @@ TryAgain2:
|
|||
|
||||
/* Kill the process in the Object Manager */
|
||||
ObKillProcess(CurrentProcess);
|
||||
PSREFTRACE(CurrentProcess);
|
||||
|
||||
/* Check if we have a section object */
|
||||
if (CurrentProcess->SectionObject)
|
||||
|
@ -768,6 +816,7 @@ TryAgain2:
|
|||
FirstEntry = KeFlushQueueApc(&Thread->Tcb, UserMode);
|
||||
if (FirstEntry)
|
||||
{
|
||||
/* Start with the first entry */
|
||||
CurrentEntry = FirstEntry;
|
||||
do
|
||||
{
|
||||
|
@ -781,7 +830,7 @@ TryAgain2:
|
|||
if (Apc->RundownRoutine)
|
||||
{
|
||||
/* Call its own routine */
|
||||
(Apc->RundownRoutine)(Apc);
|
||||
Apc->RundownRoutine(Apc);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -800,12 +849,12 @@ TryAgain2:
|
|||
|
||||
/* Flush the APC queue, which should be empty */
|
||||
FirstEntry = KeFlushQueueApc(&Thread->Tcb, KernelMode);
|
||||
if (FirstEntry)
|
||||
if ((FirstEntry) || (Thread->Tcb.CombinedApcDisable != 0))
|
||||
{
|
||||
/* Bugcheck time */
|
||||
KEBUGCHECKEX(KERNEL_APC_PENDING_DURING_EXIT,
|
||||
(ULONG_PTR)FirstEntry,
|
||||
Thread->Tcb.KernelApcDisable,
|
||||
Thread->Tcb.CombinedApcDisable,
|
||||
KeGetCurrentIrql(),
|
||||
0);
|
||||
}
|
||||
|
@ -814,8 +863,6 @@ TryAgain2:
|
|||
if (Last) KeSetProcess(&CurrentProcess->Pcb, 0, FALSE);
|
||||
|
||||
/* Terminate the Thread from the Scheduler */
|
||||
PSREFTRACE(Thread);
|
||||
PSREFTRACE(CurrentProcess);
|
||||
KeTerminateThread(0);
|
||||
}
|
||||
|
||||
|
@ -927,10 +974,11 @@ PspTerminateThreadByPointer(IN PETHREAD Thread,
|
|||
Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_TERMINATE_APC);
|
||||
|
||||
/* Set the Terminated Flag */
|
||||
Flags = Thread->CrossThreadFlags | 1;
|
||||
Flags = Thread->CrossThreadFlags | CT_TERMINATED_BIT;
|
||||
|
||||
/* Set it, and check if it was already set while we were running */
|
||||
if (!(InterlockedExchange((PLONG)&Thread->CrossThreadFlags, Flags) & 1))
|
||||
if (!(InterlockedExchange((PLONG)&Thread->CrossThreadFlags, Flags) &
|
||||
CT_TERMINATED_BIT))
|
||||
{
|
||||
/* Initialize a Kernel Mode APC to Kill the Thread */
|
||||
KeInitializeApc(Apc,
|
||||
|
@ -961,7 +1009,6 @@ PspTerminateThreadByPointer(IN PETHREAD Thread,
|
|||
ExFreePool(Apc);
|
||||
|
||||
/* Return Status */
|
||||
PSREFTRACE(Thread);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -1006,7 +1053,6 @@ PspExitProcess(IN BOOLEAN LastThread,
|
|||
}
|
||||
|
||||
/* Check if we are the last thread */
|
||||
PSREFTRACE(Process);
|
||||
if (LastThread)
|
||||
{
|
||||
/* Check if we have to set the Timer Resolution */
|
||||
|
@ -1088,7 +1134,12 @@ NtTerminateProcess(IN HANDLE ProcessHandle OPTIONAL,
|
|||
}
|
||||
|
||||
/* Lock the Process */
|
||||
ExAcquireRundownProtection(&Process->RundownProtect);
|
||||
if (!ExAcquireRundownProtection(&Process->RundownProtect))
|
||||
{
|
||||
/* Failed to lock, fal */
|
||||
ObDereferenceObject (Process);
|
||||
return STATUS_PROCESS_IS_TERMINATING;
|
||||
}
|
||||
|
||||
/* Set the delete flag */
|
||||
if (!KillByHandle) InterlockedOr((PLONG)&Process->Flags,
|
||||
|
@ -1113,7 +1164,8 @@ NtTerminateProcess(IN HANDLE ProcessHandle OPTIONAL,
|
|||
}
|
||||
|
||||
/* Move to the next thread */
|
||||
} while((Thread = PsGetNextProcessThread(Process, Thread)));
|
||||
Thread = PsGetNextProcessThread(Process, Thread);
|
||||
} while (Thread);
|
||||
}
|
||||
|
||||
/* Unlock the process */
|
||||
|
|
|
@ -397,7 +397,6 @@ PspCreateProcess(OUT PHANDLE ProcessHandle,
|
|||
(PVOID*)&Parent,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
PSREFTRACE(Parent);
|
||||
|
||||
/* If this process should be in a job but the parent isn't */
|
||||
if ((InJob) && (!Parent->Job))
|
||||
|
@ -434,7 +433,6 @@ PspCreateProcess(OUT PHANDLE ProcessHandle,
|
|||
if (!NT_SUCCESS(Status)) goto Cleanup;
|
||||
|
||||
/* Clean up the Object */
|
||||
PSREFTRACE(Process);
|
||||
RtlZeroMemory(Process, sizeof(EPROCESS));
|
||||
|
||||
/* Initialize pushlock and rundown protection */
|
||||
|
@ -485,14 +483,15 @@ PspCreateProcess(OUT PHANDLE ProcessHandle,
|
|||
if (Parent != PsInitialSystemProcess)
|
||||
{
|
||||
/* It's not, so acquire the process rundown */
|
||||
ExAcquireRundownProtection(&Process->RundownProtect);
|
||||
if (ExAcquireRundownProtection(&Process->RundownProtect))
|
||||
{
|
||||
/* If the parent has a section, use it */
|
||||
SectionObject = Parent->SectionObject;
|
||||
if (SectionObject) ObReferenceObject(SectionObject);
|
||||
|
||||
/* If the parent has a section, use it */
|
||||
SectionObject = Parent->SectionObject;
|
||||
if (SectionObject) ObReferenceObject(SectionObject);
|
||||
|
||||
/* Release process rundown */
|
||||
ExReleaseRundownProtection(&Process->RundownProtect);
|
||||
/* Release process rundown */
|
||||
ExReleaseRundownProtection(&Process->RundownProtect);
|
||||
}
|
||||
|
||||
/* If we don't have a section object */
|
||||
if (!SectionObject)
|
||||
|
@ -647,23 +646,25 @@ PspCreateProcess(OUT PHANDLE ProcessHandle,
|
|||
AccessState,
|
||||
DesiredAccess,
|
||||
1,
|
||||
(PVOID*)&Process,
|
||||
NULL,
|
||||
&hProcess);
|
||||
|
||||
/* Free the access state */
|
||||
if (AccessState) SeDeleteAccessState(AccessState);
|
||||
|
||||
/* Cleanup on failure */
|
||||
PSREFTRACE(Process);
|
||||
if (!NT_SUCCESS(Status)) goto Cleanup;
|
||||
|
||||
/* Compute Quantum and Priority */
|
||||
Process->Pcb.BasePriority = (SCHAR)PspComputeQuantumAndPriority(Process,
|
||||
0,
|
||||
&Quantum);
|
||||
ASSERT(IsListEmpty(&Process->ThreadListHead) == TRUE);
|
||||
Process->Pcb.BasePriority =
|
||||
(SCHAR)PspComputeQuantumAndPriority(Process,
|
||||
PsProcessPriorityBackground,
|
||||
&Quantum);
|
||||
Process->Pcb.QuantumReset = Quantum;
|
||||
|
||||
/* Check if we have a parent other then the initial system process */
|
||||
Process->GrantedAccess = PROCESS_TERMINATE;
|
||||
if ((Parent) && (Parent != PsInitialSystemProcess))
|
||||
{
|
||||
/* Get the process's SD */
|
||||
|
@ -683,7 +684,6 @@ PspCreateProcess(OUT PHANDLE ProcessHandle,
|
|||
SubjectContext.ClientToken = NULL;
|
||||
|
||||
/* Do the access check */
|
||||
if (!SecurityDescriptor) DPRINT1("FIX PS SDs!!\n");
|
||||
Result = SeAccessCheck(SecurityDescriptor,
|
||||
&SubjectContext,
|
||||
FALSE,
|
||||
|
@ -712,7 +712,9 @@ PspCreateProcess(OUT PHANDLE ProcessHandle,
|
|||
PROCESS_CREATE_THREAD |
|
||||
PROCESS_DUP_HANDLE |
|
||||
PROCESS_CREATE_PROCESS |
|
||||
PROCESS_SET_INFORMATION);
|
||||
PROCESS_SET_INFORMATION |
|
||||
STANDARD_RIGHTS_ALL |
|
||||
PROCESS_SET_QUOTA);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -720,14 +722,10 @@ PspCreateProcess(OUT PHANDLE ProcessHandle,
|
|||
Process->GrantedAccess = PROCESS_ALL_ACCESS;
|
||||
}
|
||||
|
||||
/* Sanity check */
|
||||
ASSERT(IsListEmpty(&Process->ThreadListHead));
|
||||
|
||||
/* Set the Creation Time */
|
||||
KeQuerySystemTime(&Process->CreateTime);
|
||||
|
||||
/* Protect against bad user-mode pointer */
|
||||
PSREFTRACE(Process);
|
||||
_SEH_TRY
|
||||
{
|
||||
/* Save the process handle */
|
||||
|
@ -753,8 +751,6 @@ Cleanup:
|
|||
if (Parent) ObDereferenceObject(Parent);
|
||||
|
||||
/* Return status to caller */
|
||||
PSREFTRACE(Process);
|
||||
if (Parent) PSREFTRACE(Parent);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -1387,8 +1383,6 @@ NtOpenProcess(OUT PHANDLE ProcessHandle,
|
|||
|
||||
/* Dereference the Process */
|
||||
ObDereferenceObject(Process);
|
||||
PSREFTRACE(Process);
|
||||
if (Thread) PSREFTRACE(Thread);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -231,7 +231,6 @@ PsLocateSystemDll(VOID)
|
|||
KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED, Status, 4, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
/* Map it */
|
||||
Status = PspMapSystemDll(PsGetCurrentProcess(), &PspSystemDllBase);
|
||||
if (!NT_SUCCESS(Status))
|
||||
|
@ -290,9 +289,7 @@ PspInitPhase0(VOID)
|
|||
MM_SYSTEMSIZE SystemSize;
|
||||
UNICODE_STRING Name;
|
||||
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
|
||||
|
||||
/* FIXME: Initialize Lock Data do it STATIC */
|
||||
ShortPsLockDelay.QuadPart = -100LL;
|
||||
ULONG i;
|
||||
|
||||
/* Get the system size */
|
||||
SystemSize = MmQuerySystemSize();
|
||||
|
@ -320,11 +317,23 @@ PspInitPhase0(VOID)
|
|||
break;
|
||||
}
|
||||
|
||||
/* Setup callbacks */
|
||||
for (i = 0; i < PSP_MAX_CREATE_THREAD_NOTIFY; i++)
|
||||
{
|
||||
ExInitializeCallBack(&PspThreadNotifyRoutine[i]);
|
||||
}
|
||||
for (i = 0; i < PSP_MAX_CREATE_PROCESS_NOTIFY; i++)
|
||||
{
|
||||
ExInitializeCallBack(&PspProcessNotifyRoutine[i]);
|
||||
}
|
||||
for (i = 0; i < PSP_MAX_LOAD_IMAGE_NOTIFY; i++)
|
||||
{
|
||||
ExInitializeCallBack(&PspLoadImageNotifyRoutine[i]);
|
||||
}
|
||||
|
||||
/* Setup the quantum table */
|
||||
PsChangeQuantumTable(FALSE, PsRawPrioritySeparation);
|
||||
|
||||
/* Setup callbacks when we implement Generic Callbacks */
|
||||
|
||||
/* Set quota settings */
|
||||
if (!PspDefaultPagedLimit) PspDefaultPagedLimit = 0;
|
||||
if (!PspDefaultNonPagedLimit) PspDefaultNonPagedLimit = 0;
|
||||
|
@ -406,6 +415,7 @@ PspInitPhase0(VOID)
|
|||
|
||||
/* Create the CID Handle table */
|
||||
PspCidTable = ExCreateHandleTable(NULL);
|
||||
if (!PspCidTable) return FALSE;
|
||||
|
||||
/* FIXME: Initialize LDT/VDM support */
|
||||
|
||||
|
@ -447,11 +457,22 @@ PspInitPhase0(VOID)
|
|||
strcpy(PsInitialSystemProcess->ImageFileName, "System");
|
||||
|
||||
/* Allocate a structure for the audit name */
|
||||
PsIdleProcess->SeAuditProcessCreationInfo.ImageFileName =
|
||||
ExAllocatePoolWithTag(PagedPool, sizeof(UNICODE_STRING), TAG_SEPA);
|
||||
if (!PsIdleProcess->SeAuditProcessCreationInfo.ImageFileName) KEBUGCHECK(0);
|
||||
PsInitialSystemProcess->SeAuditProcessCreationInfo.ImageFileName =
|
||||
ExAllocatePoolWithTag(PagedPool,
|
||||
sizeof(OBJECT_NAME_INFORMATION),
|
||||
TAG_SEPA);
|
||||
if (!PsInitialSystemProcess->SeAuditProcessCreationInfo.ImageFileName)
|
||||
{
|
||||
/* Allocation failed */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Setup the system initailization thread */
|
||||
/* Zero it */
|
||||
RtlZeroMemory(PsInitialSystemProcess->
|
||||
SeAuditProcessCreationInfo.ImageFileName,
|
||||
sizeof(OBJECT_NAME_INFORMATION));
|
||||
|
||||
/* Setup the system initialization thread */
|
||||
Status = PsCreateSystemThread(&SysThreadHandle,
|
||||
THREAD_ALL_ACCESS,
|
||||
&ObjectAttributes,
|
||||
|
|
|
@ -45,6 +45,7 @@ VOID
|
|||
NTAPI
|
||||
PspDeleteThreadSecurity(IN PETHREAD Thread)
|
||||
{
|
||||
PPS_IMPERSONATION_INFORMATION ImpersonationInfo = Thread->ImpersonationInfo;
|
||||
PAGED_CODE();
|
||||
PSTRACE(PS_SECURITY_DEBUG, "Thread: %p\n", Thread);
|
||||
|
||||
|
@ -52,14 +53,14 @@ PspDeleteThreadSecurity(IN PETHREAD Thread)
|
|||
if (Thread->ActiveImpersonationInfo)
|
||||
{
|
||||
/* Dereference its token */
|
||||
ObDereferenceObject(Thread->ImpersonationInfo->Token);
|
||||
ObDereferenceObject(ImpersonationInfo->Token);
|
||||
}
|
||||
|
||||
/* Check if we have impersonation info */
|
||||
if (Thread->ImpersonationInfo)
|
||||
if (ImpersonationInfo)
|
||||
{
|
||||
/* Free it */
|
||||
ExFreePool(Thread->ImpersonationInfo);
|
||||
ExFreePool(ImpersonationInfo);
|
||||
PspClearCrossThreadFlag(Thread, CT_ACTIVE_IMPERSONATION_INFO_BIT);
|
||||
Thread->ImpersonationInfo = NULL;
|
||||
}
|
||||
|
@ -91,7 +92,11 @@ PspInitializeProcessSecurity(IN PEPROCESS Process,
|
|||
ObFastDereferenceObject(&Parent->Token, ParentToken);
|
||||
|
||||
/* Set the new Token */
|
||||
ObInitializeFastReference(&Process->Token, NewToken);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Initailize the fast reference */
|
||||
ObInitializeFastReference(&Process->Token, NewToken);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -133,26 +138,24 @@ PspWriteTebImpersonationInfo(IN PETHREAD Thread,
|
|||
Attached = TRUE;
|
||||
}
|
||||
|
||||
/* Check if we're in a different thread */
|
||||
if (Thread != CurrentThread)
|
||||
/* Check if we're in a different thread or acquire rundown */
|
||||
if ((Thread == CurrentThread) ||
|
||||
(ExAcquireRundownProtection(&Thread->RundownProtect)))
|
||||
{
|
||||
/* Acquire thread rundown protection */
|
||||
ExAcquireRundownProtection(&Thread->RundownProtect);
|
||||
}
|
||||
|
||||
/* Check if the thread is impersonating */
|
||||
IsImpersonating = (BOOLEAN)Thread->ActiveImpersonationInfo;
|
||||
if (IsImpersonating)
|
||||
{
|
||||
/* Set TEB data */
|
||||
Teb->ImpersonationLocale = -1;
|
||||
Teb->IsImpersonating = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set TEB data */
|
||||
Teb->ImpersonationLocale = 0;
|
||||
Teb->IsImpersonating = 0;
|
||||
/* Check if the thread is impersonating */
|
||||
IsImpersonating = (BOOLEAN)Thread->ActiveImpersonationInfo;
|
||||
if (IsImpersonating)
|
||||
{
|
||||
/* Set TEB data */
|
||||
Teb->ImpersonationLocale = -1;
|
||||
Teb->IsImpersonating = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set TEB data */
|
||||
Teb->ImpersonationLocale = 0;
|
||||
Teb->IsImpersonating = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we're in a different thread */
|
||||
|
@ -162,7 +165,7 @@ PspWriteTebImpersonationInfo(IN PETHREAD Thread,
|
|||
ExReleaseRundownProtection(&Thread->RundownProtect);
|
||||
}
|
||||
|
||||
/* Dettach */
|
||||
/* Detach */
|
||||
if (Attached) KeUnstackDetachProcess(&ApcState);
|
||||
}
|
||||
|
||||
|
@ -170,29 +173,40 @@ PspWriteTebImpersonationInfo(IN PETHREAD Thread,
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
PspAssignPrimaryToken(IN PEPROCESS Process,
|
||||
IN PTOKEN Token)
|
||||
IN HANDLE Token,
|
||||
IN PACCESS_TOKEN AccessToken OPTIONAL)
|
||||
{
|
||||
PACCESS_TOKEN OldToken;
|
||||
PACCESS_TOKEN NewToken = AccessToken, OldToken;
|
||||
NTSTATUS Status;
|
||||
PAGED_CODE();
|
||||
PSTRACE(PS_SECURITY_DEBUG, "Process: %p Token: %p\n", Process, Token);
|
||||
|
||||
/* Lock the process */
|
||||
/* Check if we don't have a pointer */
|
||||
if (!AccessToken)
|
||||
{
|
||||
/* Reference it from the handle */
|
||||
Status = ObReferenceObjectByHandle(Token,
|
||||
TOKEN_ASSIGN_PRIMARY,
|
||||
SepTokenObjectType,
|
||||
ExGetPreviousMode(),
|
||||
&NewToken,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
}
|
||||
|
||||
/* Exchange tokens */
|
||||
Status = SeExchangePrimaryToken(Process, NewToken, &OldToken);
|
||||
|
||||
/* Acquire and release the lock */
|
||||
PspLockProcessSecurityExclusive(Process);
|
||||
|
||||
/* Exchange them */
|
||||
Status = SeExchangePrimaryToken(Process, Token, &OldToken);
|
||||
|
||||
/* Release the lock */
|
||||
PspUnlockProcessSecurityExclusive(Process);
|
||||
|
||||
/* Dereference Tokens and Return */
|
||||
if (NT_SUCCESS(Status)) ObDereferenceObject(OldToken);
|
||||
ObDereferenceObject(Token);
|
||||
if (AccessToken) ObDereferenceObject(NewToken);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -200,10 +214,11 @@ NTSTATUS
|
|||
NTAPI
|
||||
PspSetPrimaryToken(IN PEPROCESS Process,
|
||||
IN HANDLE TokenHandle OPTIONAL,
|
||||
IN PTOKEN Token OPTIONAL)
|
||||
IN PACCESS_TOKEN Token OPTIONAL)
|
||||
{
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
BOOLEAN IsChild;
|
||||
PACCESS_TOKEN NewToken = Token;
|
||||
NTSTATUS Status, AccessStatus;
|
||||
BOOLEAN Result, SdAllocated;
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor;
|
||||
|
@ -218,17 +233,17 @@ PspSetPrimaryToken(IN PEPROCESS Process,
|
|||
TOKEN_ASSIGN_PRIMARY,
|
||||
SepTokenObjectType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Token,
|
||||
(PVOID*)&NewToken,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
}
|
||||
|
||||
/* Check if this is a child */
|
||||
Status = SeIsTokenChild(Token, &IsChild);
|
||||
Status = SeIsTokenChild(NewToken, &IsChild);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Failed, dereference */
|
||||
if (TokenHandle) ObDereferenceObject(Token);
|
||||
if (TokenHandle) ObDereferenceObject(NewToken);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -246,7 +261,7 @@ PspSetPrimaryToken(IN PEPROCESS Process,
|
|||
}
|
||||
|
||||
/* Assign the token */
|
||||
Status = PspAssignPrimaryToken(Process, Token);
|
||||
Status = PspAssignPrimaryToken(Process, NULL, NewToken);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/*
|
||||
|
@ -264,7 +279,6 @@ PspSetPrimaryToken(IN PEPROCESS Process,
|
|||
SubjectContext.ClientToken = NULL;
|
||||
|
||||
/* Do the access check */
|
||||
if (!SecurityDescriptor) DPRINT1("FIX PS SDs!!\n");
|
||||
Result = SeAccessCheck(SecurityDescriptor,
|
||||
&SubjectContext,
|
||||
FALSE,
|
||||
|
@ -283,6 +297,19 @@ PspSetPrimaryToken(IN PEPROCESS Process,
|
|||
|
||||
/* Remove access if it failed */
|
||||
if (!Result) Process->GrantedAccess = 0;
|
||||
|
||||
/* Setup granted access */
|
||||
Process->GrantedAccess |= (PROCESS_VM_OPERATION |
|
||||
PROCESS_VM_READ |
|
||||
PROCESS_VM_WRITE |
|
||||
PROCESS_QUERY_INFORMATION |
|
||||
PROCESS_TERMINATE |
|
||||
PROCESS_CREATE_THREAD |
|
||||
PROCESS_DUP_HANDLE |
|
||||
PROCESS_CREATE_PROCESS |
|
||||
PROCESS_SET_INFORMATION |
|
||||
STANDARD_RIGHTS_ALL |
|
||||
PROCESS_SET_QUOTA);
|
||||
}
|
||||
|
||||
/* Dereference the process */
|
||||
|
@ -290,7 +317,7 @@ PspSetPrimaryToken(IN PEPROCESS Process,
|
|||
}
|
||||
|
||||
/* Dereference the token */
|
||||
if (TokenHandle) ObDereferenceObject(Token);
|
||||
if (Token) ObDereferenceObject(NewToken);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -352,7 +379,7 @@ NtOpenProcessTokenEx(IN HANDLE ProcessHandle,
|
|||
|
||||
/* Open the process token */
|
||||
Status = PsOpenTokenOfProcess(ProcessHandle, &Token);
|
||||
if(NT_SUCCESS(Status))
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Reference it by handle and dereference the pointer */
|
||||
Status = ObOpenObjectByPointer(Token,
|
||||
|
@ -365,7 +392,7 @@ NtOpenProcessTokenEx(IN HANDLE ProcessHandle,
|
|||
ObDereferenceObject(Token);
|
||||
|
||||
/* Make sure we got a handle */
|
||||
if(NT_SUCCESS(Status))
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Enter SEH for write */
|
||||
_SEH_TRY
|
||||
|
@ -487,10 +514,7 @@ PsAssignImpersonationToken(IN PETHREAD Thread,
|
|||
return STATUS_BAD_TOKEN_TYPE;
|
||||
}
|
||||
|
||||
/* Check if this is a job, which we don't support yet */
|
||||
if (Thread->ThreadsProcess->Job) KEBUGCHECK(0);
|
||||
|
||||
/* Get the impersionation level */
|
||||
/* Get the impersonation level */
|
||||
ImpersonationLevel = SeTokenImpersonationLevel(Token);
|
||||
|
||||
/* Call the impersonation API */
|
||||
|
@ -501,7 +525,7 @@ PsAssignImpersonationToken(IN PETHREAD Thread,
|
|||
ImpersonationLevel);
|
||||
|
||||
/* Dereference the token and return status */
|
||||
if (Token) ObDereferenceObject(Token);
|
||||
ObDereferenceObject(Token);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -546,13 +570,17 @@ PsRevertThreadToSelf(IN PETHREAD Thread)
|
|||
|
||||
/* Release thread security */
|
||||
PspUnlockThreadSecurityExclusive(Thread);
|
||||
|
||||
/* Check if we had a token */
|
||||
if (Token)
|
||||
{
|
||||
/* Dereference the impersonation token */
|
||||
ObDereferenceObject(Token);
|
||||
|
||||
/* Write impersonation info to the TEB */
|
||||
PspWriteTebImpersonationInfo(Thread, PsGetCurrentThread());
|
||||
}
|
||||
}
|
||||
|
||||
/* Dereference the impersonation token */
|
||||
if (Token) ObDereferenceObject(Token);
|
||||
|
||||
/* Write impersonation info to the TEB */
|
||||
PspWriteTebImpersonationInfo(Thread, PsGetCurrentThread());
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -566,7 +594,7 @@ PsImpersonateClient(IN PETHREAD Thread,
|
|||
IN BOOLEAN EffectiveOnly,
|
||||
IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
|
||||
{
|
||||
PPS_IMPERSONATION_INFORMATION Impersonation;
|
||||
PPS_IMPERSONATION_INFORMATION Impersonation, OldData;
|
||||
PTOKEN OldToken = NULL;
|
||||
PAGED_CODE();
|
||||
PSTRACE(PS_SECURITY_DEBUG, "Thread: %p, Token: %p\n", Thread, Token);
|
||||
|
@ -591,8 +619,9 @@ PsImpersonateClient(IN PETHREAD Thread,
|
|||
OldToken = Thread->ImpersonationInfo->Token;
|
||||
}
|
||||
|
||||
/* Unlock the process */
|
||||
/* Unlock the process and write TEB information */
|
||||
PspUnlockThreadSecurityExclusive(Thread);
|
||||
PspWriteTebImpersonationInfo(Thread, PsGetCurrentThread());
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -608,12 +637,15 @@ PsImpersonateClient(IN PETHREAD Thread,
|
|||
if (!Impersonation) return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
/* Update the pointer */
|
||||
if (InterlockedCompareExchangePointer(&Thread->ImpersonationInfo,
|
||||
Impersonation,
|
||||
NULL))
|
||||
OldData = InterlockedCompareExchangePointer(&Thread->
|
||||
ImpersonationInfo,
|
||||
Impersonation,
|
||||
NULL);
|
||||
if (OldData)
|
||||
{
|
||||
/* Someone beat us to it, free our copy */
|
||||
ExFreePool(Impersonation);
|
||||
Impersonation = OldData;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -644,13 +676,13 @@ PsImpersonateClient(IN PETHREAD Thread,
|
|||
|
||||
/* Unlock the thread */
|
||||
PspUnlockThreadSecurityExclusive(Thread);
|
||||
|
||||
/* Write impersonation info to the TEB */
|
||||
PspWriteTebImpersonationInfo(Thread, PsGetCurrentThread());
|
||||
}
|
||||
|
||||
/* Write impersonation info to the TEB */
|
||||
PspWriteTebImpersonationInfo(Thread, PsGetCurrentThread());
|
||||
|
||||
/* Dereference the token and return success */
|
||||
if (OldToken) ObDereferenceObject(OldToken);
|
||||
if (OldToken) PsDereferenceImpersonationToken(OldToken);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -674,9 +706,6 @@ PsReferenceEffectiveToken(IN PETHREAD Thread,
|
|||
Process = Thread->ThreadsProcess;
|
||||
if (!Thread->ActiveImpersonationInfo)
|
||||
{
|
||||
*TokenType = TokenPrimary;
|
||||
*EffectiveOnly = FALSE;
|
||||
|
||||
/* Fast Reference the Token */
|
||||
Token = ObFastReferenceObject(&Process->Token);
|
||||
|
||||
|
@ -709,6 +738,10 @@ PsReferenceEffectiveToken(IN PETHREAD Thread,
|
|||
*TokenType = TokenImpersonation;
|
||||
*EffectiveOnly = Thread->ImpersonationInfo->EffectiveOnly;
|
||||
*Level = Thread->ImpersonationInfo->ImpersonationLevel;
|
||||
|
||||
/* Unlock the Process */
|
||||
PspUnlockProcessSecurityShared(Process);
|
||||
return Token;
|
||||
}
|
||||
|
||||
/* Unlock the Process */
|
||||
|
@ -716,6 +749,8 @@ PsReferenceEffectiveToken(IN PETHREAD Thread,
|
|||
}
|
||||
|
||||
/* Return the token */
|
||||
*TokenType = TokenPrimary;
|
||||
*EffectiveOnly = FALSE;
|
||||
return Token;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,9 +51,8 @@ PspUserThreadStartup(IN PKSTART_ROUTINE StartRoutine,
|
|||
Teb->IdealProcessor = Thread->Tcb.IdealProcessor;
|
||||
}
|
||||
|
||||
/* Check if this is a system thread, or if we're hiding */
|
||||
PSREFTRACE(Thread);
|
||||
if (!(Thread->SystemThread) && !(Thread->HideFromDebugger))
|
||||
/* Check if this is a dead thread, or if we're hiding */
|
||||
if (!(Thread->DeadThread) && !(Thread->HideFromDebugger))
|
||||
{
|
||||
/* We're not, so notify the debugger */
|
||||
DbgkCreateThread(StartContext);
|
||||
|
@ -113,6 +112,30 @@ PspUserThreadStartup(IN PKSTART_ROUTINE StartRoutine,
|
|||
}
|
||||
}
|
||||
|
||||
_SEH_FILTER(PspUnhandledExceptionInSystemThread)
|
||||
{
|
||||
PEXCEPTION_POINTERS ExceptionPointers= _SEH_GetExceptionPointers();
|
||||
|
||||
/* Print debugging information */
|
||||
DPRINT1("PS: Unhandled Kernel Mode Exception Pointers = 0x%p\n",
|
||||
ExceptionPointers);
|
||||
DPRINT1("Code %x Addr %p Info0 %p Info1 %p Info2 %p Info3 %p\n",
|
||||
ExceptionPointers->ExceptionRecord->ExceptionCode,
|
||||
ExceptionPointers->ExceptionRecord->ExceptionAddress,
|
||||
ExceptionPointers->ExceptionRecord->ExceptionInformation[0],
|
||||
ExceptionPointers->ExceptionRecord->ExceptionInformation[1],
|
||||
ExceptionPointers->ExceptionRecord->ExceptionInformation[2],
|
||||
ExceptionPointers->ExceptionRecord->ExceptionInformation[3]);
|
||||
|
||||
/* Bugcheck the system */
|
||||
KeBugCheckEx(0x7E,
|
||||
ExceptionPointers->ExceptionRecord->ExceptionCode,
|
||||
(ULONG_PTR)ExceptionPointers->ExceptionRecord->ExceptionAddress,
|
||||
(ULONG_PTR)ExceptionPointers->ExceptionRecord,
|
||||
(ULONG_PTR)ExceptionPointers->ContextRecord);
|
||||
return 0;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
PspSystemThreadStartup(IN PKSTART_ROUTINE StartRoutine,
|
||||
|
@ -127,12 +150,20 @@ PspSystemThreadStartup(IN PKSTART_ROUTINE StartRoutine,
|
|||
Thread = PsGetCurrentThread();
|
||||
|
||||
/* Make sure the thread isn't gone */
|
||||
PSREFTRACE(Thread);
|
||||
if (!(Thread->Terminated) && !(Thread->DeadThread))
|
||||
_SEH_TRY
|
||||
{
|
||||
/* Call it the Start Routine */
|
||||
StartRoutine(StartContext);
|
||||
if (!(Thread->Terminated) && !(Thread->DeadThread))
|
||||
{
|
||||
/* Call it the Start Routine */
|
||||
StartRoutine(StartContext);
|
||||
}
|
||||
}
|
||||
_SEH_EXCEPT(PspUnhandledExceptionInSystemThread)
|
||||
{
|
||||
/* Bugcheck if we got here */
|
||||
KeBugCheck(KMODE_EXCEPTION_NOT_HANDLED);
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
/* Exit the thread */
|
||||
PspTerminateThreadByPointer(Thread, STATUS_SUCCESS, TRUE);
|
||||
|
@ -192,7 +223,6 @@ PspCreateThread(OUT PHANDLE ThreadHandle,
|
|||
{
|
||||
/* Reference the Process by Pointer */
|
||||
ObReferenceObject(TargetProcess);
|
||||
PSREFTRACE(TargetProcess);
|
||||
Process = TargetProcess;
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -232,7 +262,6 @@ PspCreateThread(OUT PHANDLE ThreadHandle,
|
|||
}
|
||||
|
||||
/* Zero the Object entirely */
|
||||
PSREFTRACE(Thread);
|
||||
RtlZeroMemory(Thread, sizeof(ETHREAD));
|
||||
|
||||
/* Initialize rundown protection */
|
||||
|
@ -270,7 +299,12 @@ PspCreateThread(OUT PHANDLE ThreadHandle,
|
|||
KeInitializeSpinLock(&Thread->ActiveTimerListLock);
|
||||
|
||||
/* Acquire rundown protection */
|
||||
ExAcquireRundownProtection(&Process->RundownProtect);
|
||||
if (!ExAcquireRundownProtection (&Process->RundownProtect))
|
||||
{
|
||||
/* Fail */
|
||||
ObDereferenceObject(Thread);
|
||||
return STATUS_PROCESS_IS_TERMINATING;
|
||||
}
|
||||
|
||||
/* Now let the kernel initialize the context */
|
||||
if (ThreadContext)
|
||||
|
@ -317,7 +351,6 @@ PspCreateThread(OUT PHANDLE ThreadHandle,
|
|||
}
|
||||
|
||||
/* Check if we failed */
|
||||
PSREFTRACE(Thread);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Delete the TEB if we had done */
|
||||
|
@ -400,6 +433,7 @@ PspCreateThread(OUT PHANDLE ThreadHandle,
|
|||
|
||||
/* Dereference completely to kill it */
|
||||
ObDereferenceObjectEx(Thread, 2);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Insert the Thread into the Object Manager */
|
||||
|
@ -411,7 +445,6 @@ PspCreateThread(OUT PHANDLE ThreadHandle,
|
|||
&hThread);
|
||||
|
||||
/* Delete the access state if we had one */
|
||||
PSREFTRACE(Thread);
|
||||
if (AccessState) SeDeleteAccessState(AccessState);
|
||||
|
||||
/* Check for success */
|
||||
|
@ -461,7 +494,6 @@ PspCreateThread(OUT PHANDLE ThreadHandle,
|
|||
ASSERT(!(Thread->CreateTime.HighPart & 0xF0000000));
|
||||
|
||||
/* Make sure the thread isn't dead */
|
||||
PSREFTRACE(Thread);
|
||||
if (!Thread->DeadThread)
|
||||
{
|
||||
/* Get the thread's SD */
|
||||
|
@ -493,7 +525,6 @@ PspCreateThread(OUT PHANDLE ThreadHandle,
|
|||
SubjectContext.ClientToken = NULL;
|
||||
|
||||
/* Do the access check */
|
||||
if (!SecurityDescriptor) DPRINT1("FIX PS SDs!!\n");
|
||||
Result = SeAccessCheck(SecurityDescriptor,
|
||||
&SubjectContext,
|
||||
FALSE,
|
||||
|
@ -525,14 +556,12 @@ PspCreateThread(OUT PHANDLE ThreadHandle,
|
|||
}
|
||||
|
||||
/* Dispatch thread */
|
||||
PSREFTRACE(Thread);
|
||||
KeReadyThread(&Thread->Tcb);
|
||||
|
||||
/* Dereference it, leaving only the keep-alive */
|
||||
ObDereferenceObject(Thread);
|
||||
|
||||
/* Return */
|
||||
PSREFTRACE(Thread);
|
||||
return Status;
|
||||
|
||||
/* Most annoying failure case ever, where we undo almost all manually */
|
||||
|
@ -541,7 +570,6 @@ Quickie:
|
|||
ExReleasePushLockExclusive(&Process->ProcessLock);
|
||||
|
||||
/* Uninitailize it */
|
||||
PSREFTRACE(Thread);
|
||||
KeUninitThread(&Thread->Tcb);
|
||||
|
||||
/* If we had a TEB, delete it */
|
||||
|
@ -552,7 +580,6 @@ Quickie:
|
|||
|
||||
/* Dereference the thread and return failure */
|
||||
ObDereferenceObject(Thread);
|
||||
PSREFTRACE(Thread);
|
||||
return STATUS_PROCESS_IS_TERMINATING;
|
||||
}
|
||||
|
||||
|
@ -841,7 +868,7 @@ NtCreateThread(OUT PHANDLE ThreadHandle,
|
|||
"ProcessHandle: %p Context: %p\n", ProcessHandle, ThreadContext);
|
||||
|
||||
/* Check if this was from user-mode */
|
||||
if(KeGetPreviousMode() != KernelMode)
|
||||
if (KeGetPreviousMode() != KernelMode)
|
||||
{
|
||||
/* Make sure that we got a context */
|
||||
if (!ThreadContext) return STATUS_INVALID_PARAMETER;
|
||||
|
@ -865,14 +892,12 @@ NtCreateThread(OUT PHANDLE ThreadHandle,
|
|||
/* Check the Initial TEB */
|
||||
ProbeForRead(InitialTeb, sizeof(INITIAL_TEB), sizeof(ULONG));
|
||||
SafeInitialTeb = *InitialTeb;
|
||||
}
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
/* Handle any failures in our SEH checks */
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
}
|
||||
else
|
||||
|
|
Loading…
Reference in a new issue