https://git.reactos.org/?p=reactos.git;a=commitdiff;h=632fa1cfbe32dbcc1f97d…
commit 632fa1cfbe32dbcc1f97dc96c9d6374cacf94ac7
Author: George Bișoc <george.bisoc(a)reactos.org>
AuthorDate: Sun Jul 25 11:37:02 2021 +0200
Commit: George Bișoc <george.bisoc(a)reactos.org>
CommitDate: Sat Jul 31 17:23:05 2021 +0200
[NTOS:SE] Handle the reference logon session of the token
When creating or duplicating an access token object, make sure that the logon session is getting referenced by the token must be inserted onto the logon reference member (a.k.a LogonSession) for proper logon session referencing tracking.
Also when a token object is about to be destroyed or that we are taking away a reference session from it, we must ensure that the referenced logon session data gets removed from the token in question.
CORE-17700
---
ntoskrnl/se/token.c | 47 ++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 42 insertions(+), 5 deletions(-)
diff --git a/ntoskrnl/se/token.c b/ntoskrnl/se/token.c
index a7b004ae034..46dbb725a89 100644
--- a/ntoskrnl/se/token.c
+++ b/ntoskrnl/se/token.c
@@ -865,6 +865,15 @@ SepDuplicateToken(
goto Quit;
}
+ /* Insert the referenced logon session into the token */
+ Status = SepRmInsertLogonSessionIntoToken(AccessToken);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Failed to insert the logon session into the token, bail out */
+ DPRINT1("SepRmInsertLogonSessionIntoToken() failed (Status 0x%lx)\n", Status);
+ goto Quit;
+ }
+
/* Assign the data that reside in the TOKEN's variable information area */
AccessToken->VariableLength = VariableLength;
EndMem = (PVOID)&AccessToken->VariablePart;
@@ -1164,10 +1173,23 @@ VOID
NTAPI
SepDeleteToken(PVOID ObjectBody)
{
+ NTSTATUS Status;
PTOKEN AccessToken = (PTOKEN)ObjectBody;
DPRINT("SepDeleteToken()\n");
+ /* Remove the referenced logon session from token */
+ if (AccessToken->LogonSession)
+ {
+ Status = SepRmRemoveLogonSessionFromToken(AccessToken);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Something seriously went wrong */
+ DPRINT1("SepDeleteToken(): Failed to remove the logon session from token (Status: 0x%lx)\n", Status);
+ return;
+ }
+ }
+
/* Dereference the logon session */
if ((AccessToken->TokenFlags & TOKEN_SESSION_NOT_REFERENCED) == 0)
SepRmDereferenceLogonSession(&AccessToken->AuthenticationId);
@@ -1359,6 +1381,15 @@ SepCreateToken(
goto Quit;
}
+ /* Insert the referenced logon session into the token */
+ Status = SepRmInsertLogonSessionIntoToken(AccessToken);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Failed to insert the logon session into the token, bail out */
+ DPRINT1("SepRmInsertLogonSessionIntoToken() failed (Status 0x%lx)\n", Status);
+ goto Quit;
+ }
+
/* Assign the data that reside in the TOKEN's variable information area */
AccessToken->VariableLength = VariableLength;
EndMem = (PVOID)&AccessToken->VariablePart;
@@ -3299,14 +3330,20 @@ NtSetInformationToken(
if (OldTokenFlags == Token->TokenFlags)
SessionReference = ULONG_MAX;
+ /*
+ * Otherwise if the flag was never set but just for this first time then
+ * remove the referenced logon session data from the token and dereference
+ * the logon session when needed.
+ */
+ if (SessionReference == 0)
+ {
+ SepRmRemoveLogonSessionFromToken(Token);
+ SepRmDereferenceLogonSession(&Token->AuthenticationId);
+ }
+
/* Unlock the token */
SepReleaseTokenLock(Token);
}
-
- /* Dereference the logon session if needed */
- if (SessionReference == 0)
- SepRmDereferenceLogonSession(&Token->AuthenticationId);
-
break;
}
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5e51f8dad27aff23dfde8…
commit 5e51f8dad27aff23dfde80d4abdfb4c961593063
Author: George Bișoc <george.bisoc(a)reactos.org>
AuthorDate: Sun Jul 25 11:34:45 2021 +0200
Commit: George Bișoc <george.bisoc(a)reactos.org>
CommitDate: Sat Jul 31 16:11:03 2021 +0200
[NTOS:SE] Implement logon reference insertion/removal to tokens
---
ntoskrnl/include/internal/se.h | 12 ++++
ntoskrnl/se/srm.c | 152 +++++++++++++++++++++++++++++++++++++++--
2 files changed, 158 insertions(+), 6 deletions(-)
diff --git a/ntoskrnl/include/internal/se.h b/ntoskrnl/include/internal/se.h
index aa01ef58088..98c1b9e1057 100644
--- a/ntoskrnl/include/internal/se.h
+++ b/ntoskrnl/include/internal/se.h
@@ -353,6 +353,18 @@ SepCreateImpersonationTokenDacl(
_Out_ PACL* Dacl
);
+NTSTATUS
+NTAPI
+SepRmInsertLogonSessionIntoToken(
+ _Inout_ PTOKEN Token
+);
+
+NTSTATUS
+NTAPI
+SepRmRemoveLogonSessionFromToken(
+ _Inout_ PTOKEN Token
+);
+
CODE_SEG("INIT")
VOID
NTAPI
diff --git a/ntoskrnl/se/srm.c b/ntoskrnl/se/srm.c
index 23fa3b02120..90809a907e1 100644
--- a/ntoskrnl/se/srm.c
+++ b/ntoskrnl/se/srm.c
@@ -1,11 +1,10 @@
/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
- * FILE: ntoskrnl/se/srm.c
+ * PROJECT: ReactOS Kernel
+ * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Security Reference Monitor Server
- *
- * PROGRAMMERS: Timo Kreuzer (timo.kreuzer(a)reactos.org)
- * Pierre Schweitzer (pierre(a)reactos.org)
+ * COPYRIGHT: Copyright Timo Kreuzer <timo.kreuzer(a)reactos.org>
+ * Copyright Pierre Schweitzer <pierre(a)reactos.org>
+ * Copyright 2021 George Bișoc <george.bisoc(a)reactos.org>
*/
/* INCLUDES *******************************************************************/
@@ -315,6 +314,147 @@ SepRmSetAuditEvent(
return STATUS_SUCCESS;
}
+/**
+ * @brief
+ * Inserts a logon session into an access token specified by the
+ * caller.
+ *
+ * @param[in,out] Token
+ * An access token where the logon session is about to be inserted
+ * in.
+ *
+ * @return
+ * STATUS_SUCCESS is returned if the logon session has been inserted into
+ * the token successfully. STATUS_NO_SUCH_LOGON_SESSION is returned when no logon
+ * session has been found with the matching ID of the token and as such
+ * we've failed to add the logon session to the token. STATUS_INSUFFICIENT_RESOURCES
+ * is returned if memory pool allocation for the new session has failed.
+ */
+NTSTATUS
+NTAPI
+SepRmInsertLogonSessionIntoToken(
+ _Inout_ PTOKEN Token)
+{
+ PSEP_LOGON_SESSION_REFERENCES LogonSession;
+ PAGED_CODE();
+
+ /* Ensure that our token is not some plain garbage */
+ ASSERT(Token);
+
+ /* Acquire the database lock */
+ KeAcquireGuardedMutex(&SepRmDbLock);
+
+ for (LogonSession = SepLogonSessions;
+ LogonSession != NULL;
+ LogonSession = LogonSession->Next)
+ {
+ /*
+ * The insertion of a logon session into the token has to be done
+ * only IF the authentication ID of the token matches with the ID
+ * of the logon itself.
+ */
+ if (RtlEqualLuid(&LogonSession->LogonId, &Token->AuthenticationId))
+ {
+ break;
+ }
+ }
+
+ /* If we reach this then we cannot proceed further */
+ if (LogonSession == NULL)
+ {
+ DPRINT1("SepRmInsertLogonSessionIntoToken(): Couldn't insert the logon session into the specific access token!\n");
+ KeReleaseGuardedMutex(&SepRmDbLock);
+ return STATUS_NO_SUCH_LOGON_SESSION;
+ }
+
+ /*
+ * Allocate the session that we are going
+ * to insert it to the token.
+ */
+ Token->LogonSession = ExAllocatePoolWithTag(PagedPool,
+ sizeof(SEP_LOGON_SESSION_REFERENCES),
+ TAG_LOGON_SESSION);
+ if (Token->LogonSession == NULL)
+ {
+ DPRINT1("SepRmInsertLogonSessionIntoToken(): Couldn't allocate new logon session into the memory pool!\n");
+ KeReleaseGuardedMutex(&SepRmDbLock);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /*
+ * Begin copying the logon session references data from the
+ * session whose ID matches with the token authentication ID to
+ * the new session we've allocated blocks of pool memory for it.
+ */
+ Token->LogonSession->Next = LogonSession->Next;
+ Token->LogonSession->LogonId = LogonSession->LogonId;
+ Token->LogonSession->ReferenceCount = LogonSession->ReferenceCount;
+ Token->LogonSession->Flags = LogonSession->Flags;
+ Token->LogonSession->pDeviceMap = LogonSession->pDeviceMap;
+ InsertHeadList(&LogonSession->TokenList, &Token->LogonSession->TokenList);
+
+ /* Release the database lock and we're done */
+ KeReleaseGuardedMutex(&SepRmDbLock);
+ return STATUS_SUCCESS;
+}
+
+/**
+ * @brief
+ * Removes a logon session from an access token.
+ *
+ * @param[in,out] Token
+ * An access token whose logon session is to be removed from it.
+ *
+ * @return
+ * STATUS_SUCCESS is returned if the logon session has been removed from
+ * the token successfully. STATUS_NO_SUCH_LOGON_SESSION is returned when no logon
+ * session has been found with the matching ID of the token and as such
+ * we've failed to remove the logon session from the token.
+ */
+NTSTATUS
+NTAPI
+SepRmRemoveLogonSessionFromToken(
+ _Inout_ PTOKEN Token)
+{
+ PSEP_LOGON_SESSION_REFERENCES LogonSession;
+ PAGED_CODE();
+
+ /* Ensure that our token is not some plain garbage */
+ ASSERT(Token);
+
+ /* Acquire the database lock */
+ KeAcquireGuardedMutex(&SepRmDbLock);
+
+ for (LogonSession = SepLogonSessions;
+ LogonSession != NULL;
+ LogonSession = LogonSession->Next)
+ {
+ /*
+ * Remove the logon session only when the IDs of the token and the
+ * logon match.
+ */
+ if (RtlEqualLuid(&LogonSession->LogonId, &Token->AuthenticationId))
+ {
+ break;
+ }
+ }
+
+ /* They don't match */
+ if (LogonSession == NULL)
+ {
+ DPRINT1("SepRmRemoveLogonSessionFromToken(): Couldn't remove the logon session from the access token!\n");
+ KeReleaseGuardedMutex(&SepRmDbLock);
+ return STATUS_NO_SUCH_LOGON_SESSION;
+ }
+
+ /* Now it's time to delete the logon session from the token */
+ RemoveEntryList(&Token->LogonSession->TokenList);
+ ExFreePoolWithTag(Token->LogonSession, TAG_LOGON_SESSION);
+
+ /* Release the database lock and we're done */
+ KeReleaseGuardedMutex(&SepRmDbLock);
+ return STATUS_SUCCESS;
+}
static
NTSTATUS