[NTOSKRNL] On process primary token change, dereference device map
[reactos.git] / ntoskrnl / ps / security.c
index 4a9c091..619ff56 100644 (file)
@@ -217,18 +217,18 @@ PspSetPrimaryToken(IN PEPROCESS Process,
                    IN PACCESS_TOKEN Token OPTIONAL)
 {
     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    BOOLEAN IsChild;
+    BOOLEAN IsChildOrSibling;
     PACCESS_TOKEN NewToken = Token;
     NTSTATUS Status, AccessStatus;
     BOOLEAN Result, SdAllocated;
     PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
     SECURITY_SUBJECT_CONTEXT SubjectContext;
+
     PSTRACE(PS_SECURITY_DEBUG, "Process: %p Token: %p\n", Process, Token);
 
-    /* Make sure we got a handle */
-    if (TokenHandle)
+    /* Reference the token by handle if we don't already have a token object */
+    if (!Token)
     {
-        /* Reference it */
         Status = ObReferenceObjectByHandle(TokenHandle,
                                            TOKEN_ASSIGN_PRIMARY,
                                            SeTokenObjectType,
@@ -238,24 +238,38 @@ PspSetPrimaryToken(IN PEPROCESS Process,
         if (!NT_SUCCESS(Status)) return Status;
     }
 
-    /* Check if this is a child */
-    Status = SeIsTokenChild(NewToken, &IsChild);
+    /*
+     * Check whether this token is a child or sibling of the current process token.
+     * NOTE: On Windows Vista+ both of these checks (together with extra steps)
+     * are now performed by a new SeIsTokenAssignableToProcess() helper.
+     */
+    Status = SeIsTokenChild(NewToken, &IsChildOrSibling);
     if (!NT_SUCCESS(Status))
     {
         /* Failed, dereference */
-        if (TokenHandle) ObDereferenceObject(NewToken);
+        if (!Token) ObDereferenceObject(NewToken);
         return Status;
     }
+    if (!IsChildOrSibling)
+    {
+        Status = SeIsTokenSibling(NewToken, &IsChildOrSibling);
+        if (!NT_SUCCESS(Status))
+        {
+            /* Failed, dereference */
+            if (!Token) ObDereferenceObject(NewToken);
+            return Status;
+        }
+    }
 
     /* Check if this was an independent token */
-    if (!IsChild)
+    if (!IsChildOrSibling)
     {
         /* Make sure we have the privilege to assign a new one */
         if (!SeSinglePrivilegeCheck(SeAssignPrimaryTokenPrivilege,
                                     PreviousMode))
         {
             /* Failed, dereference */
-            if (TokenHandle) ObDereferenceObject(NewToken);
+            if (!Token) ObDereferenceObject(NewToken);
             return STATUS_PRIVILEGE_NOT_HELD;
         }
     }
@@ -311,10 +325,18 @@ PspSetPrimaryToken(IN PEPROCESS Process,
                                        STANDARD_RIGHTS_ALL |
                                        PROCESS_SET_QUOTA);
         }
+
+        /*
+         * In case LUID device maps are enable, we may not be using
+         * system device map for this process, but a logon LUID based
+         * device map. Because we change primary token, this usage is
+         * no longer valid, so dereference the process device map
+         */
+        if (ObIsLUIDDeviceMapsEnabled()) ObDereferenceDeviceMap(Process);
     }
 
     /* Dereference the token */
-    if (TokenHandle) ObDereferenceObject(NewToken);
+    if (!Token) ObDereferenceObject(NewToken);
     return Status;
 }
 
@@ -371,6 +393,9 @@ NtOpenProcessTokenEx(IN HANDLE ProcessHandle,
         _SEH2_END;
     }
 
+    /* Validate object attributes */
+    HandleAttributes = ObpValidateAttributes(HandleAttributes, PreviousMode);
+
     /* Open the process token */
     Status = PsOpenTokenOfProcess(ProcessHandle, &Token);
     if (NT_SUCCESS(Status))
@@ -688,35 +713,19 @@ NTAPI
 PsReferenceEffectiveToken(IN PETHREAD Thread,
                           OUT IN PTOKEN_TYPE TokenType,
                           OUT PBOOLEAN EffectiveOnly,
-                          OUT PSECURITY_IMPERSONATION_LEVEL Level)
+                          OUT PSECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
 {
     PEPROCESS Process;
     PACCESS_TOKEN Token = NULL;
+
     PAGED_CODE();
+
     PSTRACE(PS_SECURITY_DEBUG,
             "Thread: %p, TokenType: %p\n", Thread, TokenType);
 
     /* Check if we don't have impersonation info */
     Process = Thread->ThreadsProcess;
-    if (!Thread->ActiveImpersonationInfo)
-    {
-        /* Fast Reference the Token */
-        Token = ObFastReferenceObject(&Process->Token);
-
-        /* Check if we got the Token or if we got locked */
-        if (!Token)
-        {
-            /* Lock the Process */
-            PspLockProcessSecurityShared(Process);
-
-            /* Do a Locked Fast Reference */
-            Token = ObFastReferenceObjectLocked(&Process->Token);
-
-            /* Unlock the Process */
-            PspUnlockProcessSecurityShared(Process);
-        }
-    }
-    else
+    if (Thread->ActiveImpersonationInfo)
     {
         /* Lock the Process */
         PspLockProcessSecurityShared(Process);
@@ -731,7 +740,7 @@ PsReferenceEffectiveToken(IN PETHREAD Thread,
             /* Return data to caller */
             *TokenType = TokenImpersonation;
             *EffectiveOnly = Thread->ImpersonationInfo->EffectiveOnly;
-            *Level = Thread->ImpersonationInfo->ImpersonationLevel;
+            *ImpersonationLevel = Thread->ImpersonationInfo->ImpersonationLevel;
 
             /* Unlock the Process */
             PspUnlockProcessSecurityShared(Process);
@@ -742,9 +751,26 @@ PsReferenceEffectiveToken(IN PETHREAD Thread,
         PspUnlockProcessSecurityShared(Process);
     }
 
+    /* Fast Reference the Token */
+    Token = ObFastReferenceObject(&Process->Token);
+
+    /* Check if we got the Token or if we got locked */
+    if (!Token)
+    {
+        /* Lock the Process */
+        PspLockProcessSecurityShared(Process);
+
+        /* Do a Locked Fast Reference */
+        Token = ObFastReferenceObjectLocked(&Process->Token);
+
+        /* Unlock the Process */
+        PspUnlockProcessSecurityShared(Process);
+    }
+
     /* Return the token */
     *TokenType = TokenPrimary;
     *EffectiveOnly = FALSE;
+    // NOTE: ImpersonationLevel is left untouched on purpose!
     return Token;
 }
 
@@ -820,10 +846,10 @@ PsDereferencePrimaryToken(IN PACCESS_TOKEN PrimaryToken)
 BOOLEAN
 NTAPI
 PsDisableImpersonation(IN PETHREAD Thread,
-                       IN PSE_IMPERSONATION_STATE ImpersonationState)
+                       OUT PSE_IMPERSONATION_STATE ImpersonationState)
 {
     PPS_IMPERSONATION_INFORMATION Impersonation = NULL;
-    LONG NewValue, OldValue;
+    LONG OldFlags;
     PAGED_CODE();
     PSTRACE(PS_SECURITY_DEBUG,
             "Thread: %p State: %p\n", Thread, ImpersonationState);
@@ -835,19 +861,11 @@ PsDisableImpersonation(IN PETHREAD Thread,
         PspLockThreadSecurityExclusive(Thread);
 
         /* Disable impersonation */
-        OldValue = Thread->CrossThreadFlags;
-        do
-        {
-            /* Attempt to change the flag */
-            NewValue =
-                InterlockedCompareExchange((PLONG)&Thread->CrossThreadFlags,
-                                           OldValue &~
-                                           CT_ACTIVE_IMPERSONATION_INFO_BIT,
-                                           OldValue);
-        } while (NewValue != OldValue);
+        OldFlags = PspClearCrossThreadFlag(Thread,
+                                           CT_ACTIVE_IMPERSONATION_INFO_BIT);
 
         /* Make sure nobody disabled it behind our back */
-        if (NewValue & CT_ACTIVE_IMPERSONATION_INFO_BIT)
+        if (OldFlags & CT_ACTIVE_IMPERSONATION_INFO_BIT)
         {
             /* Copy the old state */
             Impersonation = Thread->ImpersonationInfo;