[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:
Alex Ionescu 2007-01-18 09:44:49 +00:00
parent ccee43a360
commit 9522e0a02b
11 changed files with 355 additions and 211 deletions

View file

@ -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(

View file

@ -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
); );
// //

View file

@ -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

View file

@ -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)

View file

@ -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;
} }
} }

View file

@ -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
{ {

View file

@ -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 */

View file

@ -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
{ {

View file

@ -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,

View file

@ -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;
} }

View file

@ -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