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