Author: ion Date: Sat Jul 22 20:03:12 2006 New Revision: 23226
URL: http://svn.reactos.org/svn/reactos?rev=23226&view=rev Log: - 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.
Modified: trunk/reactos/base/system/winlogon/winlogon.c trunk/reactos/base/system/winlogon/winlogon.h trunk/reactos/ntoskrnl/include/internal/ps.h trunk/reactos/ntoskrnl/include/internal/se.h trunk/reactos/ntoskrnl/ps/query.c trunk/reactos/ntoskrnl/ps/security.c trunk/reactos/ntoskrnl/se/token.c
Modified: trunk/reactos/base/system/winlogon/winlogon.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/winlogon/winlog... ============================================================================== --- trunk/reactos/base/system/winlogon/winlogon.c (original) +++ trunk/reactos/base/system/winlogon/winlogon.c Sat Jul 22 20:03:12 2006 @@ -534,6 +534,7 @@ LPSTR lpCmdLine, int nShowCmd) { + BOOLEAN Old; #if SUPPORT_CONSOLESTART // WCHAR LoginName[255]; // WCHAR Password[255]; @@ -554,6 +555,9 @@ ExitProcess(0); return 0; } + + /* Get privilege */ + RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &Old);
#if START_LSASS if (StartProcess(L"StartLsass"))
Modified: trunk/reactos/base/system/winlogon/winlogon.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/winlogon/winlog... ============================================================================== --- trunk/reactos/base/system/winlogon/winlogon.h (original) +++ trunk/reactos/base/system/winlogon/winlogon.h Sat Jul 22 20:03:12 2006 @@ -33,6 +33,7 @@ #include <winwlx.h> #include <rtlfuncs.h> #include <exfuncs.h> +#include <setypes.h>
#include <reactos/winlogon.h>
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 Sat Jul 22 20:03:12 2006 @@ -59,10 +59,11 @@ );
NTSTATUS -STDCALL -PspAssignPrimaryToken( - PEPROCESS Process, - HANDLE TokenHandle +NTAPI +PspSetPrimaryToken( + IN PEPROCESS Process, + IN HANDLE TokenHandle OPTIONAL, + IN PTOKEN Token OPTIONAL );
PETHREAD
Modified: trunk/reactos/ntoskrnl/include/internal/se.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/s... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/se.h (original) +++ trunk/reactos/ntoskrnl/include/internal/se.h Sat Jul 22 20:03:12 2006 @@ -130,6 +130,13 @@ );
NTSTATUS +NTAPI +SeIsTokenChild( + IN PTOKEN Token, + OUT PBOOLEAN IsChild +); + +NTSTATUS STDCALL SepCreateImpersonationTokenDacl( PTOKEN Token,
Modified: trunk/reactos/ntoskrnl/ps/query.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ps/query.c?rev=232... ============================================================================== --- trunk/reactos/ntoskrnl/ps/query.c (original) +++ trunk/reactos/ntoskrnl/ps/query.c Sat Jul 22 20:03:12 2006 @@ -581,7 +581,7 @@ if (!NT_SUCCESS(Status)) break;
/* Assign the actual token */ - Status = PspAssignPrimaryToken(Process, TokenHandle); + Status = PspSetPrimaryToken(Process, TokenHandle, NULL); break;
/* Hard error processing */
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 Sat Jul 22 20:03:12 2006 @@ -25,7 +25,7 @@ KeEnterCriticalRegion();
/* Lock the Process */ - //ExAcquirePushLockShared(&Process->ProcessLock); + ExAcquirePushLockShared(&Process->ProcessLock); }
/* FIXME: Turn into Macro */ @@ -34,7 +34,31 @@ 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,25 +143,89 @@ NTSTATUS NTAPI PspAssignPrimaryToken(IN PEPROCESS Process, - IN HANDLE TokenHandle) -{ - PACCESS_TOKEN Token, OldToken; + IN PTOKEN Token) +{ + PACCESS_TOKEN OldToken; NTSTATUS Status; - - /* Reference the Token */ - Status = ObReferenceObjectByHandle(TokenHandle, - TOKEN_ASSIGN_PRIMARY, - SepTokenObjectType, - KeGetPreviousMode(), - (PVOID*)&Token, - NULL); - if (!NT_SUCCESS(Status)) return Status; + PAGED_CODE(); + + /* 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; }
Modified: trunk/reactos/ntoskrnl/se/token.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/se/token.c?rev=232... ============================================================================== --- trunk/reactos/ntoskrnl/se/token.c (original) +++ trunk/reactos/ntoskrnl/se/token.c Sat Jul 22 20:03:12 2006 @@ -366,6 +366,36 @@
/* Return status */ 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; }
/*