Author: ion Date: Thu Jul 20 09:33:03 2006 New Revision: 23179
URL: http://svn.reactos.org/svn/reactos?rev=23179&view=rev Log: - Move ExGetPreviousMode to \ex, it's not a Ps function - Organize thread.c into private/public functions properly. - Do another pass of formatting fixes and function annotation. - Fix a bug in PspSystemStartup. - Properly hold object references towards a thread that's being created. - Set the Thread->GrantedAccess value. - Update NtOpenThread to use an Access State since these work now and Ob respects them, and also add a special hack present on NT: If the SeDEbugPrivilege is present, then the caller will get full thread access regardless of his rights.
Modified: trunk/reactos/ntoskrnl/KrnlFun.c trunk/reactos/ntoskrnl/ex/sysinfo.c trunk/reactos/ntoskrnl/include/internal/ob.h trunk/reactos/ntoskrnl/ps/thread.c
Modified: trunk/reactos/ntoskrnl/KrnlFun.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/KrnlFun.c?rev=2317... ============================================================================== --- trunk/reactos/ntoskrnl/KrnlFun.c (original) +++ trunk/reactos/ntoskrnl/KrnlFun.c Thu Jul 20 09:33:03 2006 @@ -35,6 +35,7 @@ // - Add security calls where necessary. // - Add tracing. // - Fix crash on shutdown due to possibly incorrect win32k uninitailization. +// - Add failure/race checks for thread creation. // // Ob: // - Possible bug in deferred deletion under Cc Rewrite branch.
Modified: trunk/reactos/ntoskrnl/ex/sysinfo.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/sysinfo.c?rev=2... ============================================================================== --- trunk/reactos/ntoskrnl/ex/sysinfo.c (original) +++ trunk/reactos/ntoskrnl/ex/sysinfo.c Thu Jul 20 09:33:03 2006 @@ -22,6 +22,16 @@ VOID MmPrintMemoryStatistic(VOID);
/* FUNCTIONS *****************************************************************/ + +/* + * @implemented + */ +KPROCESSOR_MODE +NTAPI +ExGetPreviousMode (VOID) +{ + return (KPROCESSOR_MODE)PsGetCurrentThread()->Tcb.PreviousMode; +}
/* * @unimplemented
Modified: trunk/reactos/ntoskrnl/include/internal/ob.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/o... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/ob.h (original) +++ trunk/reactos/ntoskrnl/include/internal/ob.h Thu Jul 20 09:33:03 2006 @@ -192,6 +192,13 @@ IN PVOID Object );
+LONG +FASTCALL +ObReferenceObjectEx( + IN PVOID Object, + IN ULONG Count +); + VOID NTAPI ObpReapObject(
Modified: trunk/reactos/ntoskrnl/ps/thread.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ps/thread.c?rev=23... ============================================================================== --- trunk/reactos/ntoskrnl/ps/thread.c (original) +++ trunk/reactos/ntoskrnl/ps/thread.c Thu Jul 20 09:33:03 2006 @@ -15,8 +15,6 @@
/* GLOBALS ******************************************************************/
-extern LIST_ENTRY PsActiveProcessHead; -extern PEPROCESS PsIdleProcess; extern PVOID PspSystemDllEntryPoint; extern PVOID PspSystemDllBase; extern PHANDLE_TABLE PspCidTable; @@ -24,12 +22,12 @@ extern ULONG MmReadClusterSize; POBJECT_TYPE PsThreadType = NULL;
-/* FUNCTIONS ***************************************************************/ +/* PRIVATE FUNCTIONS *********************************************************/
VOID NTAPI -PspUserThreadStartup(PKSTART_ROUTINE StartRoutine, - PVOID StartContext) +PspUserThreadStartup(IN PKSTART_ROUTINE StartRoutine, + IN PVOID StartContext) { PETHREAD Thread; PTEB Teb; @@ -109,8 +107,8 @@
VOID NTAPI -PspSystemThreadStartup(PKSTART_ROUTINE StartRoutine, - PVOID StartContext) +PspSystemThreadStartup(IN PKSTART_ROUTINE StartRoutine, + IN PVOID StartContext) { PETHREAD Thread;
@@ -119,7 +117,7 @@ Thread = PsGetCurrentThread();
/* Make sure the thread isn't gone */ - if (!(Thread->Terminated) || !(Thread->DeadThread)) + if (!(Thread->Terminated) && !(Thread->DeadThread)) { /* Call it the Start Routine */ StartRoutine(StartContext); @@ -329,65 +327,68 @@ /* Notify Thread Creation */ PspRunCreateThreadNotifyRoutines(Thread, TRUE);
+ /* Reference ourselves as a keep-alive */ + ObReferenceObjectEx(Thread, 2); + /* Suspend the Thread if we have to */ if (CreateSuspended) KeSuspendThread(&Thread->Tcb);
/* Check if we were already terminated */ - if (Thread->Terminated) - { - /* Force us to wake up to terminate */ - KeForceResumeThread(&Thread->Tcb); - } - - /* Reference ourselves as a keep-alive */ - ObReferenceObject(Thread); + if (Thread->Terminated) KeForceResumeThread(&Thread->Tcb);
/* Insert the Thread into the Object Manager */ - Status = ObInsertObject((PVOID)Thread, + Status = ObInsertObject(Thread, NULL, DesiredAccess, 0, NULL, &hThread); - if(NT_SUCCESS(Status)) + if (NT_SUCCESS(Status)) { /* Wrap in SEH to protect against bad user-mode pointers */ _SEH_TRY { /* Return Cid and Handle */ - if(ClientId) *ClientId = Thread->Cid; + if (ClientId) *ClientId = Thread->Cid; *ThreadHandle = hThread; } _SEH_HANDLE { + /* Get the exception code */ Status = _SEH_GetExceptionCode(); } _SEH_END; }
- /* FIXME: SECURITY */ + /* Set the thread access mask */ + Thread->GrantedAccess = THREAD_ALL_ACCESS;
/* Dispatch thread */ OldIrql = KeAcquireDispatcherDatabaseLock (); KiReadyThread(&Thread->Tcb); KeReleaseDispatcherDatabaseLock(OldIrql);
+ /* Dereference it, leaving only the keep-alive */ + ObDereferenceObject(Thread); + /* Return */ return Status; }
+/* PUBLIC FUNCTIONS **********************************************************/ + /* * @implemented */ NTSTATUS NTAPI -PsCreateSystemThread(PHANDLE ThreadHandle, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes, - HANDLE ProcessHandle, - PCLIENT_ID ClientId, - PKSTART_ROUTINE StartRoutine, - PVOID StartContext) +PsCreateSystemThread(OUT PHANDLE ThreadHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN HANDLE ProcessHandle, + IN PCLIENT_ID ClientId, + IN PKSTART_ROUTINE StartRoutine, + IN PVOID StartContext) { PEPROCESS TargetProcess = NULL; HANDLE Handle = ProcessHandle; @@ -429,8 +430,8 @@ KeEnterCriticalRegion();
/* Get the CID Handle Entry */ - if ((CidEntry = ExMapHandleToPointer(PspCidTable, - ThreadId))) + CidEntry = ExMapHandleToPointer(PspCidTable, ThreadId); + if (CidEntry) { /* Get the Process */ FoundThread = CidEntry->Object; @@ -438,7 +439,7 @@ /* Make sure it's really a process */ if (FoundThread->Tcb.DispatcherHeader.Type == ThreadObject) { - /* Reference and return it */ + /* FIXME: Safe Reference and return it */ ObReferenceObject(FoundThread); *Thread = FoundThread; Status = STATUS_SUCCESS; @@ -447,7 +448,7 @@ /* Unlock the Entry */ ExUnlockHandleTableEntry(PspCidTable, CidEntry); } - + /* Return to caller */ KeLeaveCriticalRegion(); return Status; @@ -460,7 +461,7 @@ NTAPI PsGetCurrentThreadId(VOID) { - return(PsGetCurrentThread()->Cid.UniqueThread); + return PsGetCurrentThread()->Cid.UniqueThread; }
/* @@ -580,7 +581,7 @@ NTAPI PsIsThreadTerminating(IN PETHREAD Thread) { - return (Thread->Terminated ? TRUE : FALSE); + return Thread->Terminated ? TRUE : FALSE; }
/* @@ -588,9 +589,9 @@ */ BOOLEAN NTAPI -PsIsSystemThread(PETHREAD Thread) -{ - return (Thread->SystemThread ? TRUE: FALSE); +PsIsSystemThread(IN PETHREAD Thread) +{ + return Thread->SystemThread ? TRUE: FALSE; }
/* @@ -598,7 +599,7 @@ */ BOOLEAN NTAPI -PsIsThreadImpersonating(PETHREAD Thread) +PsIsThreadImpersonating(IN PETHREAD Thread) { return Thread->ActiveImpersonationInfo; } @@ -608,8 +609,8 @@ */ VOID NTAPI -PsSetThreadHardErrorsAreDisabled(PETHREAD Thread, - BOOLEAN HardErrorsAreDisabled) +PsSetThreadHardErrorsAreDisabled(IN PETHREAD Thread, + IN BOOLEAN HardErrorsAreDisabled) { Thread->HardErrorsAreDisabled = HardErrorsAreDisabled; } @@ -619,8 +620,8 @@ */ VOID NTAPI -PsSetThreadWin32Thread(PETHREAD Thread, - PVOID Win32Thread) +PsSetThreadWin32Thread(IN PETHREAD Thread, + IN PVOID Win32Thread) { Thread->Tcb.Win32Thread = Win32Thread; } @@ -629,7 +630,7 @@ NTAPI NtCreateThread(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN HANDLE ProcessHandle, OUT PCLIENT_ID ClientId, IN PCONTEXT ThreadContext, @@ -703,39 +704,41 @@ NtOpenThread(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, - IN PCLIENT_ID ClientId OPTIONAL) -{ - KPROCESSOR_MODE PreviousMode; + IN PCLIENT_ID ClientId OPTIONAL) +{ + KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); CLIENT_ID SafeClientId; ULONG Attributes = 0; HANDLE hThread = NULL; NTSTATUS Status = STATUS_SUCCESS; PETHREAD Thread; BOOLEAN HasObjectName = FALSE; - + ACCESS_STATE AccessState; + AUX_DATA AuxData; PAGED_CODE();
- PreviousMode = KeGetPreviousMode(); - - /* Probe the paraemeters */ - if(PreviousMode != KernelMode) - { + /* Check if we were called from user mode */ + if (PreviousMode != KernelMode) + { + /* Enter SEH for probing */ _SEH_TRY { + /* Probe the thread handle */ ProbeForWriteHandle(ThreadHandle);
- if(ClientId != NULL) + /* Check for a CID structure */ + if (ClientId) { - ProbeForRead(ClientId, - sizeof(CLIENT_ID), - sizeof(ULONG)); - + /* Probe and capture it */ + ProbeForRead(ClientId, sizeof(CLIENT_ID), sizeof(ULONG)); SafeClientId = *ClientId; ClientId = &SafeClientId; }
- /* just probe the object attributes structure, don't capture it - completely. This is done later if necessary */ + /* + * Just probe the object attributes structure, don't capture it + * completely. This is done later if necessary + */ ProbeForRead(ObjectAttributes, sizeof(OBJECT_ATTRIBUTES), sizeof(ULONG)); @@ -744,22 +747,47 @@ } _SEH_HANDLE { + /* Get the exception code */ Status = _SEH_GetExceptionCode(); } _SEH_END; - - if(!NT_SUCCESS(Status)) return Status; + if (!NT_SUCCESS(Status)) return Status; } else { + /* Otherwise just get the data directly */ HasObjectName = (ObjectAttributes->ObjectName != NULL); Attributes = ObjectAttributes->Attributes; } - - if (HasObjectName && ClientId != NULL) - { - /* can't pass both, n object name and a client id */ - return STATUS_INVALID_PARAMETER_MIX; + + /* Can't pass both, fail */ + if ((HasObjectName) && (ClientId)) return STATUS_INVALID_PARAMETER_MIX; + + /* Create an access state */ + Status = SeCreateAccessState(&AccessState, + &AuxData, + DesiredAccess, + &PsProcessType->TypeInfo.GenericMapping); + if (!NT_SUCCESS(Status)) return Status; + + /* Check if this is a debugger */ + if (SeSinglePrivilegeCheck(SeDebugPrivilege, PreviousMode)) + { + /* Did he want full access? */ + if (AccessState.RemainingDesiredAccess & MAXIMUM_ALLOWED) + { + /* Give it to him */ + AccessState.PreviouslyGrantedAccess |= THREAD_ALL_ACCESS; + } + else + { + /* Otherwise just give every other access he could want */ + AccessState.PreviouslyGrantedAccess |= + AccessState.RemainingDesiredAccess; + } + + /* The caller desires nothing else now */ + AccessState.RemainingDesiredAccess = 0; }
/* Open by name if one was given */ @@ -769,10 +797,13 @@ Status = ObOpenObjectByName(ObjectAttributes, PsThreadType, PreviousMode, - NULL, - DesiredAccess, + &AccessState, + 0, NULL, &hThread); + + /* Get rid of the access state */ + SeDeleteAccessState(&AccessState); } else if (ClientId) { @@ -780,35 +811,38 @@ if (ClientId->UniqueProcess) { /* Get the Process */ - Status = PsLookupProcessThreadByCid(ClientId, - NULL, - &Thread); + Status = PsLookupProcessThreadByCid(ClientId, NULL, &Thread); } else { /* Get the Process */ - Status = PsLookupThreadByThreadId(ClientId->UniqueThread, - &Thread); - } - - /* Fail if we didn't find anything */ - if(!NT_SUCCESS(Status)) return Status; + Status = PsLookupThreadByThreadId(ClientId->UniqueThread, &Thread); + } + + /* Check if we didn't find anything */ + if (!NT_SUCCESS(Status)) + { + /* Get rid of the access state and return */ + SeDeleteAccessState(&AccessState); + return Status; + }
/* Open the Thread Object */ Status = ObOpenObjectByPointer(Thread, Attributes, - NULL, - DesiredAccess, + &AccessState, + 0, PsThreadType, PreviousMode, &hThread);
- /* Dereference the thread */ + /* Delete the access state and dereference the thread */ + SeDeleteAccessState(&AccessState); ObDereferenceObject(Thread); } else { - /* neither an object name nor a client id was passed */ + /* Neither an object name nor a client id was passed */ return STATUS_INVALID_PARAMETER_MIX; }
@@ -823,6 +857,7 @@ } _SEH_HANDLE { + /* Get the exception code */ Status = _SEH_GetExceptionCode(); } _SEH_END; @@ -832,22 +867,15 @@ return Status; }
+/* + * @implemented + */ NTSTATUS NTAPI NtYieldExecution(VOID) { KiDispatchThread(Ready); - return(STATUS_SUCCESS); -} - -/* - * @implemented - */ -KPROCESSOR_MODE -NTAPI -ExGetPreviousMode (VOID) -{ - return (KPROCESSOR_MODE)PsGetCurrentThread()->Tcb.PreviousMode; + return STATUS_SUCCESS; }
/* EOF */