[NTOS:SE] Do not use a global lock for tokens (#3445)
authorGeorge Bișoc <george.bisoc@reactos.org>
Fri, 5 Feb 2021 09:10:19 +0000 (10:10 +0100)
committerGitHub <noreply@github.com>
Fri, 5 Feb 2021 09:10:19 +0000 (12:10 +0300)
In Windows Server 2003 the lock is initialised on a per-token basis, that is, the lock resource is created in SepDuplicateToken() and SepCreateToken() functions. This ensures that the lock initialisation is done locally for the specific token thus avoiding the need of a global lock.

ntoskrnl/include/internal/tag.h
ntoskrnl/se/token.c
sdk/include/ndk/setypes.h

index 3e838c8..804a1a9 100644 (file)
 #define TAG_SE_HANDLES_TAB    'aHeS'
 #define TAG_SE_DIR_BUFFER     'bDeS'
 #define TAG_SE_PROXY_DATA     'dPoT'
+#define TAG_SE_TOKEN_LOCK     'lTeS'
 
 /* LPC Tags */
 #define TAG_LPC_MESSAGE   'McpL'
index d7158d7..1f12e01 100644 (file)
@@ -27,7 +27,6 @@ typedef struct _TOKEN_AUDIT_POLICY_INFORMATION
 /* GLOBALS ********************************************************************/
 
 POBJECT_TYPE SeTokenObjectType = NULL;
-ERESOURCE SepTokenLock; // FIXME: Global lock!
 
 TOKEN_SOURCE SeSystemTokenSource = {"*SYSTEM*", {0}};
 LUID SeSystemAuthenticationId = SYSTEM_LUID;
@@ -83,6 +82,59 @@ static const INFORMATION_CLASS_INFO SeTokenInformationClass[] = {
 
 /* FUNCTIONS *****************************************************************/
 
+/**
+ * @brief
+ * Creates a lock for the token.
+ * 
+ * @param[in,out] Token
+ * A token which lock has to be created.
+ *
+ * @return
+ * STATUS_SUCCESS if the pool allocation and resource initialisation have
+ * completed successfully, otherwise STATUS_INSUFFICIENT_RESOURCES on a
+ * pool allocation failure.
+ */
+static
+NTSTATUS
+SepCreateTokenLock(
+    _Inout_ PTOKEN Token)
+{
+    PAGED_CODE();
+
+    Token->TokenLock = ExAllocatePoolWithTag(NonPagedPool,
+                                             sizeof(ERESOURCE),
+                                             TAG_SE_TOKEN_LOCK);
+    if (Token->TokenLock == NULL)
+    {
+        DPRINT1("SepCreateTokenLock(): Failed to allocate memory!\n");
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    ExInitializeResourceLite(Token->TokenLock);
+    return STATUS_SUCCESS;
+}
+
+/**
+ * @brief
+ * Deletes a lock of a token.
+ *
+ * @param[in,out] Token
+ * A token which contains the lock.
+ *
+ * @return
+ * Nothing.
+ */
+static
+VOID
+SepDeleteTokenLock(
+    _Inout_ PTOKEN Token)
+{
+    PAGED_CODE();
+
+    ExDeleteResourceLite(Token->TokenLock);
+    ExFreePoolWithTag(Token->TokenLock, TAG_SE_TOKEN_LOCK);
+}
+
 static NTSTATUS
 SepCompareTokens(IN PTOKEN FirstToken,
                  IN PTOKEN SecondToken,
@@ -477,7 +529,13 @@ SepDuplicateToken(
     AccessToken->TokenType = TokenType;
     AccessToken->ImpersonationLevel = Level;
 
-    AccessToken->TokenLock = &SepTokenLock; // FIXME: Global lock!
+    /* Initialise the lock for the access token */
+    Status = SepCreateTokenLock(AccessToken);
+    if (!NT_SUCCESS(Status))
+    {
+        ObDereferenceObject(AccessToken);
+        return Status;
+    }
 
     /* Copy the immutable fields */
     RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
@@ -491,7 +549,6 @@ SepDuplicateToken(
     AccessToken->ExpirationTime = Token->ExpirationTime;
     AccessToken->OriginatingLogonSession = Token->OriginatingLogonSession;
 
-
     /* Lock the source token and copy the mutable fields */
     SepAcquireTokenLockExclusive(Token);
 
@@ -819,6 +876,10 @@ SepDeleteToken(PVOID ObjectBody)
     if ((AccessToken->TokenFlags & TOKEN_SESSION_NOT_REFERENCED) == 0)
         SepRmDereferenceLogonSession(&AccessToken->AuthenticationId);
 
+    /* Delete the token lock */
+    if (AccessToken->TokenLock)
+        SepDeleteTokenLock(AccessToken);
+
     /* Delete the dynamic information area */
     if (AccessToken->DynamicPart)
         ExFreePoolWithTag(AccessToken->DynamicPart, TAG_TOKEN_DYNAMIC);
@@ -833,8 +894,6 @@ SepInitializeTokenImplementation(VOID)
     UNICODE_STRING Name;
     OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
 
-    ExInitializeResource(&SepTokenLock); // FIXME: Global lock!
-
     DPRINT("Creating Token Object Type\n");
 
     /* Initialize the Token type */
@@ -976,7 +1035,10 @@ SepCreateToken(
     AccessToken->TokenType = TokenType;
     AccessToken->ImpersonationLevel = ImpersonationLevel;
 
-    AccessToken->TokenLock = &SepTokenLock; // FIXME: Global lock!
+    /* Initialise the lock for the access token */
+    Status = SepCreateTokenLock(AccessToken);
+    if (!NT_SUCCESS(Status))
+        goto Quit;
 
     RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
                 &TokenSource->SourceIdentifier);
index 55e0d8f..7071ce8 100644 (file)
@@ -188,7 +188,7 @@ typedef struct _TOKEN
     LUID AuthenticationId;                            /* 0x18 */
     LUID ParentTokenId;                               /* 0x20 */
     LARGE_INTEGER ExpirationTime;                     /* 0x28 */
-    struct _ERESOURCE *TokenLock;                     /* 0x30 */
+    PERESOURCE TokenLock;                             /* 0x30 */
     SEP_AUDIT_POLICY  AuditPolicy;                    /* 0x38 */
     LUID ModifiedId;                                  /* 0x40 */
     ULONG SessionId;                                  /* 0x48 */