From e685ced6d03ccc6131234dc1622565a1efb937b9 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Sun, 23 Jul 2006 17:56:57 +0000 Subject: [PATCH] - Add ObGetObjectSecurity calls like in PspCreateProcess to check the thread's level of access towards itself. - Add code to handle two more failure (the last, afaics) cases. - Get rid of 2 kernel fun entries. svn path=/trunk/; revision=23250 --- reactos/ntoskrnl/KrnlFun.c | 2 - reactos/ntoskrnl/ps/thread.c | 89 ++++++++++++++++++++++++++++++++++-- 2 files changed, 86 insertions(+), 5 deletions(-) diff --git a/reactos/ntoskrnl/KrnlFun.c b/reactos/ntoskrnl/KrnlFun.c index b08b5286af7..71550912e5f 100644 --- a/reactos/ntoskrnl/KrnlFun.c +++ b/reactos/ntoskrnl/KrnlFun.c @@ -27,9 +27,7 @@ // Ps: // - Figure out why processes don't die. // - Generate process cookie for user-more thread. -// - Add security calls where necessary for thread creation. // - Add tracing. -// - Add failure/race checks for thread creation. // // Ob: // - Possible bug in deferred deletion under Cc Rewrite branch. diff --git a/reactos/ntoskrnl/ps/thread.c b/reactos/ntoskrnl/ps/thread.c index 4e9df2b1874..ab8571591fe 100644 --- a/reactos/ntoskrnl/ps/thread.c +++ b/reactos/ntoskrnl/ps/thread.c @@ -144,11 +144,14 @@ PspCreateThread(OUT PHANDLE ThreadHandle, PTEB TebBase = NULL; KIRQL OldIrql; KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); - NTSTATUS Status; + NTSTATUS Status, AccessStatus; HANDLE_TABLE_ENTRY CidEntry; ACCESS_STATE LocalAccessState; PACCESS_STATE AccessState = &LocalAccessState; AUX_DATA AuxData; + BOOLEAN Result, SdAllocated; + PSECURITY_DESCRIPTOR SecurityDescriptor; + SECURITY_SUBJECT_CONTEXT SubjectContext; PAGED_CODE(); /* If we were called from PsCreateSystemThread, then we're kernel mode */ @@ -402,8 +405,26 @@ PspCreateThread(OUT PHANDLE ThreadHandle, { /* Get the exception code */ Status = _SEH_GetExceptionCode(); + + /* Thread insertion failed, thread is dead */ + InterlockedOr(&Thread->CrossThreadFlags, CT_DEAD_THREAD_BIT); + + /* If we were suspended, wake it up */ + if (CreateSuspended) KeResumeThread(&Thread->Tcb); + + /* Dispatch thread */ + OldIrql = KeAcquireDispatcherDatabaseLock (); + KiReadyThread(&Thread->Tcb); + KeReleaseDispatcherDatabaseLock(OldIrql); + + /* Dereference it, leaving only the keep-alive */ + ObDereferenceObject(Thread); + + /* Close its handle, killing it */ + ObCloseHandle(ThreadHandle, PreviousMode); } _SEH_END; + if (!NT_SUCCESS(Status)) return Status; } else { @@ -418,8 +439,70 @@ PspCreateThread(OUT PHANDLE ThreadHandle, KeQuerySystemTime(&Thread->CreateTime); ASSERT(!(Thread->CreateTime.HighPart & 0xF0000000)); - /* Set the thread access mask */ - Thread->GrantedAccess = THREAD_ALL_ACCESS; + /* Make sure the thread isn't dead */ + if (!Thread->DeadThread) + { + /* Get the thread's SD */ + Status = ObGetObjectSecurity(Thread, + &SecurityDescriptor, + &SdAllocated); + if (!NT_SUCCESS(Status)) + { + /* Thread insertion failed, thread is dead */ + InterlockedOr(&Thread->CrossThreadFlags, CT_DEAD_THREAD_BIT); + + /* If we were suspended, wake it up */ + if (CreateSuspended) KeResumeThread(&Thread->Tcb); + + /* Dispatch thread */ + OldIrql = KeAcquireDispatcherDatabaseLock (); + KiReadyThread(&Thread->Tcb); + KeReleaseDispatcherDatabaseLock(OldIrql); + + /* Dereference it, leaving only the keep-alive */ + ObDereferenceObject(Thread); + + /* Close its handle, killing it */ + ObCloseHandle(ThreadHandle, PreviousMode); + return Status; + } + + /* Create the subject context */ + SubjectContext.ProcessAuditId = Process; + SubjectContext.PrimaryToken = PsReferencePrimaryToken(Process); + SubjectContext.ClientToken = NULL; + + /* Do the access check */ + if (!SecurityDescriptor) DPRINT1("FIX PS SDs!!\n"); + Result = SeAccessCheck(SecurityDescriptor, + &SubjectContext, + FALSE, + MAXIMUM_ALLOWED, + 0, + NULL, + &PsThreadType->TypeInfo.GenericMapping, + PreviousMode, + &Thread->GrantedAccess, + &AccessStatus); + + /* Dereference the token and let go the SD */ + ObFastDereferenceObject(&Process->Token, + SubjectContext.PrimaryToken); + ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated); + + /* Remove access if it failed */ + if (!Result) Process->GrantedAccess = 0; + + /* Set least some minimum access */ + Thread->GrantedAccess |= (THREAD_TERMINATE | + THREAD_SET_INFORMATION | + THREAD_QUERY_INFORMATION); + } + else + { + /* Set the thread access mask to maximum */ + Thread->GrantedAccess = THREAD_ALL_ACCESS; + } /* Dispatch thread */ OldIrql = KeAcquireDispatcherDatabaseLock ();