From db04986dcefdeefba8d58695f14643989e83473c Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Sat, 22 Jul 2006 16:03:12 +0000 Subject: [PATCH] - Give winlogon SE_ASSIGNPRIMARYTOKEN_PRIVILEGE because it was lacking it and would fail under this kernel patch. - PspAssignPrimaryToken was good enough for actually *assigning* the token, but when NtSetInfoProcess is called with ProcessPrimaryToken, we want to do a lot more then just randomly assigning it. Added PspSetPrimaryToken which first verifies if the token being assigned is a child token and if not, checks for SeAssignPrimaryTokenPrivilege. Also added a fixme for more code that's needed, to actually re-calculate the process's granted access towards itself. Also added thread-safety. svn path=/trunk/; revision=23226 --- reactos/base/system/winlogon/winlogon.c | 4 + reactos/base/system/winlogon/winlogon.h | 1 + reactos/ntoskrnl/include/internal/ps.h | 9 +- reactos/ntoskrnl/include/internal/se.h | 7 ++ reactos/ntoskrnl/ps/query.c | 2 +- reactos/ntoskrnl/ps/security.c | 114 +++++++++++++++++++++--- reactos/ntoskrnl/se/token.c | 30 +++++++ 7 files changed, 149 insertions(+), 18 deletions(-) diff --git a/reactos/base/system/winlogon/winlogon.c b/reactos/base/system/winlogon/winlogon.c index 64c336be08f..a14d8b18f96 100644 --- a/reactos/base/system/winlogon/winlogon.c +++ b/reactos/base/system/winlogon/winlogon.c @@ -534,6 +534,7 @@ WinMain(HINSTANCE hInstance, LPSTR lpCmdLine, int nShowCmd) { + BOOLEAN Old; #if SUPPORT_CONSOLESTART // WCHAR LoginName[255]; // WCHAR Password[255]; @@ -555,6 +556,9 @@ WinMain(HINSTANCE hInstance, return 0; } + /* Get privilege */ + RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &Old); + #if START_LSASS if (StartProcess(L"StartLsass")) { diff --git a/reactos/base/system/winlogon/winlogon.h b/reactos/base/system/winlogon/winlogon.h index d8422cf520f..7b9521beb85 100644 --- a/reactos/base/system/winlogon/winlogon.h +++ b/reactos/base/system/winlogon/winlogon.h @@ -33,6 +33,7 @@ #include #include #include +#include #include diff --git a/reactos/ntoskrnl/include/internal/ps.h b/reactos/ntoskrnl/include/internal/ps.h index 7e1f0336f06..0eab1f124d9 100644 --- a/reactos/ntoskrnl/include/internal/ps.h +++ b/reactos/ntoskrnl/include/internal/ps.h @@ -59,10 +59,11 @@ PsOpenTokenOfProcess( ); NTSTATUS -STDCALL -PspAssignPrimaryToken( - PEPROCESS Process, - HANDLE TokenHandle +NTAPI +PspSetPrimaryToken( + IN PEPROCESS Process, + IN HANDLE TokenHandle OPTIONAL, + IN PTOKEN Token OPTIONAL ); PETHREAD diff --git a/reactos/ntoskrnl/include/internal/se.h b/reactos/ntoskrnl/include/internal/se.h index a39f0f6f1a3..c0cb0fd45b4 100644 --- a/reactos/ntoskrnl/include/internal/se.h +++ b/reactos/ntoskrnl/include/internal/se.h @@ -129,6 +129,13 @@ SeSubProcessToken( IN ULONG SessionId ); +NTSTATUS +NTAPI +SeIsTokenChild( + IN PTOKEN Token, + OUT PBOOLEAN IsChild +); + NTSTATUS STDCALL SepCreateImpersonationTokenDacl( diff --git a/reactos/ntoskrnl/ps/query.c b/reactos/ntoskrnl/ps/query.c index aab9bf4d652..58f6165cf05 100644 --- a/reactos/ntoskrnl/ps/query.c +++ b/reactos/ntoskrnl/ps/query.c @@ -581,7 +581,7 @@ NtSetInformationProcess(IN HANDLE ProcessHandle, if (!NT_SUCCESS(Status)) break; /* Assign the actual token */ - Status = PspAssignPrimaryToken(Process, TokenHandle); + Status = PspSetPrimaryToken(Process, TokenHandle, NULL); break; /* Hard error processing */ diff --git a/reactos/ntoskrnl/ps/security.c b/reactos/ntoskrnl/ps/security.c index eb47d596587..45e4a3b7af8 100644 --- a/reactos/ntoskrnl/ps/security.c +++ b/reactos/ntoskrnl/ps/security.c @@ -25,7 +25,7 @@ PspLockProcessSecurityShared(IN PEPROCESS Process) KeEnterCriticalRegion(); /* Lock the Process */ - //ExAcquirePushLockShared(&Process->ProcessLock); + ExAcquirePushLockShared(&Process->ProcessLock); } /* FIXME: Turn into Macro */ @@ -34,7 +34,31 @@ NTAPI PspUnlockProcessSecurityShared(IN PEPROCESS Process) { /* Unlock the Process */ - //ExReleasePushLockShared(&Process->ProcessLock); + ExReleasePushLockShared(&Process->ProcessLock); + + /* Leave Critical Region */ + KeLeaveCriticalRegion(); +} + +/* FIXME: Turn into Macro */ +VOID +NTAPI +PspLockProcessSecurityExclusive(IN PEPROCESS Process) +{ + /* Enter a Critical Region */ + KeEnterCriticalRegion(); + + /* Lock the Process */ + ExAcquirePushLockExclusive(&Process->ProcessLock); +} + +/* FIXME: Turn into Macro */ +VOID +NTAPI +PspUnlockProcessSecurityExclusive(IN PEPROCESS Process) +{ + /* Unlock the Process */ + ExReleasePushLockExclusive(&Process->ProcessLock); /* Leave Critical Region */ KeLeaveCriticalRegion(); @@ -119,28 +143,92 @@ PspInitializeProcessSecurity(IN PEPROCESS Process, NTSTATUS NTAPI PspAssignPrimaryToken(IN PEPROCESS Process, - IN HANDLE TokenHandle) + IN PTOKEN Token) { - PACCESS_TOKEN Token, OldToken; + PACCESS_TOKEN OldToken; NTSTATUS Status; + PAGED_CODE(); - /* Reference the Token */ - Status = ObReferenceObjectByHandle(TokenHandle, - TOKEN_ASSIGN_PRIMARY, - SepTokenObjectType, - KeGetPreviousMode(), - (PVOID*)&Token, - NULL); - if (!NT_SUCCESS(Status)) return Status; + /* Lock the process */ + PspLockProcessSecurityExclusive(Process); /* Exchange them */ Status = SeExchangePrimaryToken(Process, Token, &OldToken); - /* Derefernece Tokens and Return */ + /* Release the lock */ + PspUnlockProcessSecurityExclusive(Process); + + /* Dereference Tokens and Return */ + if (NT_SUCCESS(Status)) ObDereferenceObject(OldToken); ObDereferenceObject(Token); return Status; } +NTSTATUS +NTAPI +PspSetPrimaryToken(IN PEPROCESS Process, + IN HANDLE TokenHandle OPTIONAL, + IN PTOKEN Token OPTIONAL) +{ + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + BOOLEAN IsChild; + NTSTATUS Status; + + /* Make sure we got a handle */ + if (TokenHandle) + { + /* Reference it */ + Status = ObReferenceObjectByHandle(TokenHandle, + TOKEN_ASSIGN_PRIMARY, + SepTokenObjectType, + PreviousMode, + (PVOID*)&Token, + NULL); + if (!NT_SUCCESS(Status)) return Status; + } + + /* Check if this is a child */ + Status = SeIsTokenChild(Token, &IsChild); + if (!NT_SUCCESS(Status)) + { + /* Failed, dereference */ + if (TokenHandle) ObDereferenceObject(Token); + return Status; + } + + /* Check if this was an independent token */ + if (!IsChild) + { + /* Make sure we have the privilege to assign a new one */ + if (!SeSinglePrivilegeCheck(SeAssignPrimaryTokenPrivilege, + PreviousMode)) + { + /* Failed, dereference */ + if (TokenHandle) ObDereferenceObject(Token); + return STATUS_PRIVILEGE_NOT_HELD; + } + } + + /* Assign the token */ + Status = PspAssignPrimaryToken(Process, Token); + if (NT_SUCCESS(Status)) + { + /* + * The idea here is that we need to completely reverify + * if the process still has access to itself under this new + * token, by doing an SeAccessCheck with the Primary Token and + * the SD of the Process (ObGetObjectSecurity). + * In the really twisted case where we lose access to ourselves, + * we would set Process->GrantedAccess to 0. + */ + DPRINT1("Process security not complete\n"); + } + + /* Dereference the token */ + if (TokenHandle) ObDereferenceObject(Token); + return Status; +} + /* FUNCTIONS *****************************************************************/ /* diff --git a/reactos/ntoskrnl/se/token.c b/reactos/ntoskrnl/se/token.c index 3882aa75f43..0f5052cc304 100644 --- a/reactos/ntoskrnl/se/token.c +++ b/reactos/ntoskrnl/se/token.c @@ -368,6 +368,36 @@ SeSubProcessToken(IN PTOKEN ParentToken, return Status; } +NTSTATUS +NTAPI +SeIsTokenChild(IN PTOKEN Token, + OUT PBOOLEAN IsChild) +{ + PTOKEN ProcessToken; + LUID ProcessLuid, CallerLuid; + + /* Assume failure */ + *IsChild = FALSE; + + /* Reference the process token */ + ProcessToken = PsReferencePrimaryToken(PsGetCurrentProcess()); + + /* Get the ID */ + ProcessLuid = ProcessToken->TokenId; + + /* Dereference the token */ + ObFastDereferenceObject(&PsGetCurrentProcess()->Token, ProcessToken); + + /* Get our LUID */ + CallerLuid = Token->TokenId; + + /* Compare the LUIDs */ + if (RtlEqualLuid(&CallerLuid, &ProcessLuid)) *IsChild = TRUE; + + /* Return success */ + return STATUS_SUCCESS; +} + /* * @unimplemented */