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