https://git.reactos.org/?p=reactos.git;a=commitdiff;h=985468d08a82d9e1eac69…
commit 985468d08a82d9e1eac6902656518829987667df
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Mon May 23 01:56:32 2022 +0200
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Mon May 23 19:30:37 2022 +0200
[NTOS:SE] Replace a bunch of RtlCopyLuid() calls into direct assignations (#4523)
Nowadays' compilers support such direct structure assignations,
and our existing codebase already uses that in other places.
---
ntoskrnl/se/token.c | 38 +++++++++++++++-----------------------
1 file changed, 15 insertions(+), 23 deletions(-)
diff --git a/ntoskrnl/se/token.c b/ntoskrnl/se/token.c
index 0c5296fe114..e773358b356 100644
--- a/ntoskrnl/se/token.c
+++ b/ntoskrnl/se/token.c
@@ -1047,8 +1047,7 @@ SepDuplicateToken(
}
/* Copy the immutable fields */
- RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
- &Token->TokenSource.SourceIdentifier);
+ AccessToken->TokenSource.SourceIdentifier = Token->TokenSource.SourceIdentifier;
RtlCopyMemory(AccessToken->TokenSource.SourceName,
Token->TokenSource.SourceName,
sizeof(Token->TokenSource.SourceName));
@@ -1062,7 +1061,7 @@ SepDuplicateToken(
SepAcquireTokenLockShared(Token);
AccessToken->SessionId = Token->SessionId;
- RtlCopyLuid(&AccessToken->ModifiedId, &Token->ModifiedId);
+ AccessToken->ModifiedId = Token->ModifiedId;
AccessToken->TokenFlags = Token->TokenFlags & ~TOKEN_SESSION_NOT_REFERENCED;
@@ -1097,7 +1096,7 @@ SepDuplicateToken(
AccessToken->CreateMethod = TOKEN_DUPLICATE_METHOD;
#endif
- /* Assign the data that reside in the TOKEN's variable information area */
+ /* Assign the data that reside in the token's variable information area */
AccessToken->VariableLength = VariableLength;
EndMem = (PVOID)&AccessToken->VariablePart;
@@ -1264,7 +1263,7 @@ SepDuplicateToken(
// other data, the code will require adaptations.
//
- /* Now allocate the TOKEN's dynamic information area and set the data */
+ /* Now allocate the token's dynamic information area and set the data */
AccessToken->DynamicAvailable = 0; // Unused memory in the dynamic area.
AccessToken->DynamicPart = NULL;
if (Token->DynamicPart && Token->DefaultDacl)
@@ -1810,8 +1809,7 @@ SepCreateToken(
/* Zero out the buffer and initialize the token */
RtlZeroMemory(AccessToken, TotalSize);
- RtlCopyLuid(&AccessToken->TokenId, &TokenId);
-
+ AccessToken->TokenId = TokenId;
AccessToken->TokenType = TokenType;
AccessToken->ImpersonationLevel = ImpersonationLevel;
@@ -1820,19 +1818,18 @@ SepCreateToken(
if (!NT_SUCCESS(Status))
goto Quit;
- RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
- &TokenSource->SourceIdentifier);
+ AccessToken->TokenSource.SourceIdentifier = TokenSource->SourceIdentifier;
RtlCopyMemory(AccessToken->TokenSource.SourceName,
TokenSource->SourceName,
sizeof(TokenSource->SourceName));
AccessToken->ExpirationTime = *ExpirationTime;
- RtlCopyLuid(&AccessToken->ModifiedId, &ModifiedId);
+ AccessToken->ModifiedId = ModifiedId;
AccessToken->TokenFlags = TokenFlags & ~TOKEN_SESSION_NOT_REFERENCED;
/* Copy and reference the logon session */
- RtlCopyLuid(&AccessToken->AuthenticationId, AuthenticationId);
+ AccessToken->AuthenticationId = *AuthenticationId;
Status = SepRmReferenceLogonSession(&AccessToken->AuthenticationId);
if (!NT_SUCCESS(Status))
{
@@ -1878,7 +1875,7 @@ SepCreateToken(
AccessToken->CreateMethod = TOKEN_CREATE_METHOD;
#endif
- /* Assign the data that reside in the TOKEN's variable information area */
+ /* Assign the data that reside in the token's variable information area */
AccessToken->VariableLength = VariableLength;
EndMem = (PVOID)&AccessToken->VariablePart;
@@ -1960,7 +1957,7 @@ SepCreateToken(
AccessToken->PrimaryGroup = AccessToken->UserAndGroups[PrimaryGroupIndex].Sid;
AccessToken->DefaultOwnerIndex = DefaultOwnerIndex;
- /* Now allocate the TOKEN's dynamic information area and set the data */
+ /* Now allocate the token's dynamic information area and set the data */
AccessToken->DynamicAvailable = 0; // Unused memory in the dynamic area.
AccessToken->DynamicPart = NULL;
if (DefaultDacl != NULL)
@@ -2181,16 +2178,14 @@ SepPerformTokenFiltering(
AccessToken->ImpersonationLevel = Token->ImpersonationLevel;
/* Copy the immutable fields */
- RtlCopyLuid(&AccessToken->TokenSource.SourceIdentifier,
- &Token->TokenSource.SourceIdentifier);
+ AccessToken->TokenSource.SourceIdentifier = Token->TokenSource.SourceIdentifier;
RtlCopyMemory(AccessToken->TokenSource.SourceName,
Token->TokenSource.SourceName,
sizeof(Token->TokenSource.SourceName));
- RtlCopyLuid(&AccessToken->AuthenticationId, &Token->AuthenticationId);
- RtlCopyLuid(&AccessToken->ParentTokenId, &Token->TokenId);
- RtlCopyLuid(&AccessToken->OriginatingLogonSession,
- &Token->OriginatingLogonSession);
+ AccessToken->AuthenticationId = Token->AuthenticationId;
+ AccessToken->ParentTokenId = Token->TokenId;
+ AccessToken->OriginatingLogonSession = Token->OriginatingLogonSession;
AccessToken->ExpirationTime = Token->ExpirationTime;
@@ -4100,8 +4095,7 @@ NtQueryInformationToken(
{
if (TokenInformationLength >= RequiredLength)
{
- RtlCopyLuid(&to->OriginatingLogonSession,
- &Token->AuthenticationId);
+ to->OriginatingLogonSession = Token->AuthenticationId;
}
else
{
@@ -5436,9 +5430,7 @@ NtAdjustGroupsToken(
Quit:
/* Allocate a new ID for the token as we made changes */
if (ChangesMade)
- {
ExAllocateLocallyUniqueId(&Token->ModifiedId);
- }
/* Unlock and dereference the token */
SepReleaseTokenLock(Token);
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=487d8601f9700a04f302a…
commit 487d8601f9700a04f302a37c4fe399eab92da23e
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Fri May 20 02:33:00 2022 +0200
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Mon May 23 19:30:36 2022 +0200
[NTOS:SE] SepPerformTokenFiltering(): Fix corruption of DynamicPart (#4523)
The problem is that EndMem is changed to point to the DynamicPart of
the token, but the code after that expects it to still point into the
VariablePart instead.
Problem fixed by moving the insertion of RestrictedSids much sooner
(where the original ones are also being copied).
---
ntoskrnl/se/token.c | 122 ++++++++++++++++++++++++++--------------------------
1 file changed, 61 insertions(+), 61 deletions(-)
diff --git a/ntoskrnl/se/token.c b/ntoskrnl/se/token.c
index 65018f60f3f..0c5296fe114 100644
--- a/ntoskrnl/se/token.c
+++ b/ntoskrnl/se/token.c
@@ -1277,8 +1277,8 @@ SepDuplicateToken(
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Quit;
}
- EndMem = (PVOID)AccessToken->DynamicPart;
+ EndMem = (PVOID)AccessToken->DynamicPart;
AccessToken->DefaultDacl = EndMem;
RtlCopyMemory(AccessToken->DefaultDacl,
@@ -1973,8 +1973,8 @@ SepCreateToken(
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Quit;
}
- EndMem = (PVOID)AccessToken->DynamicPart;
+ EndMem = (PVOID)AccessToken->DynamicPart;
AccessToken->DefaultDacl = EndMem;
RtlCopyMemory(AccessToken->DefaultDacl,
@@ -2306,6 +2306,64 @@ SepPerformTokenFiltering(
}
}
+ /*
+ * Insert the restricted SIDs into the token on
+ * the request by the caller.
+ */
+ if (RestrictedSidsIntoToken != NULL)
+ {
+ for (RestrictedSidsInList = 0; RestrictedSidsInList < RestrictedSidsCount; RestrictedSidsInList++)
+ {
+ /* Did the caller assign attributes to the restricted SIDs? */
+ if (RestrictedSidsIntoToken[RestrictedSidsInList].Attributes != 0)
+ {
+ /* There mustn't be any attributes, bail out */
+ DPRINT1("SepPerformTokenFiltering(): There mustn't be any attributes to restricted SIDs!\n");
+ Status = STATUS_INVALID_PARAMETER;
+ goto Quit;
+ }
+ }
+
+ /*
+ * Ensure that the token can hold the restricted SIDs
+ * (the variable length is calculated at the beginning
+ * of the routine call).
+ */
+ ASSERT(VariableLength >= RestrictedSidsLength);
+
+ /*
+ * Now let's begin inserting the restricted SIDs into the filtered
+ * access token from the list the caller gave us.
+ */
+ AccessToken->RestrictedSidCount = RestrictedSidsCount;
+ AccessToken->RestrictedSids = EndMem;
+ EndMem = (PVOID)((ULONG_PTR)EndMem + RestrictedSidsLength);
+ VariableLength -= RestrictedSidsLength;
+
+ RtlCopyMemory(AccessToken->RestrictedSids,
+ RestrictedSidsIntoToken,
+ AccessToken->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES));
+
+ /*
+ * As we've copied the restricted SIDs into
+ * the token, we must assign them the following
+ * combination of attributes SE_GROUP_ENABLED,
+ * SE_GROUP_ENABLED_BY_DEFAULT and SE_GROUP_MANDATORY.
+ * With such attributes we estabilish that restricting
+ * SIDs into the token are enabled for access checks.
+ */
+ for (RestrictedSidsInToken = 0; RestrictedSidsInToken < AccessToken->RestrictedSidCount; RestrictedSidsInToken++)
+ {
+ AccessToken->RestrictedSids[RestrictedSidsInToken].Attributes |= (SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY);
+ }
+
+ /*
+ * As we added restricted SIDs into the token, mark
+ * it as restricted.
+ */
+ AccessToken->TokenFlags |= TOKEN_IS_RESTRICTED;
+ }
+
/* Search for the primary group */
Status = SepFindPrimaryGroupAndDefaultOwner(AccessToken,
Token->PrimaryGroup,
@@ -2517,64 +2575,6 @@ SepPerformTokenFiltering(
}
}
- /*
- * Insert the restricted SIDs into the token on
- * the request by the caller.
- */
- if (RestrictedSidsIntoToken != NULL)
- {
- for (RestrictedSidsInList = 0; RestrictedSidsInList < RestrictedSidsCount; RestrictedSidsInList++)
- {
- /* Did the caller assign attributes to the restricted SIDs? */
- if (RestrictedSidsIntoToken[RestrictedSidsInList].Attributes != 0)
- {
- /* There mustn't be any attributes, bail out */
- DPRINT1("SepPerformTokenFiltering(): There mustn't be any attributes to restricted SIDs!\n");
- Status = STATUS_INVALID_PARAMETER;
- goto Quit;
- }
- }
-
- /*
- * Ensure that the token can hold the restricted SIDs
- * (the variable length is calculated at the beginning
- * of the routine call).
- */
- ASSERT(VariableLength >= RestrictedSidsLength);
-
- /*
- * Now let's begin inserting the restricted SIDs into the filtered
- * access token from the list the caller gave us.
- */
- AccessToken->RestrictedSidCount = RestrictedSidsCount;
- AccessToken->RestrictedSids = EndMem;
- EndMem = (PVOID)((ULONG_PTR)EndMem + RestrictedSidsLength);
- VariableLength -= RestrictedSidsLength;
-
- RtlCopyMemory(AccessToken->RestrictedSids,
- RestrictedSidsIntoToken,
- AccessToken->RestrictedSidCount * sizeof(SID_AND_ATTRIBUTES));
-
- /*
- * As we've copied the restricted SIDs into
- * the token, we must assign them the following
- * combination of attributes SE_GROUP_ENABLED,
- * SE_GROUP_ENABLED_BY_DEFAULT and SE_GROUP_MANDATORY.
- * With such attributes we estabilish that restricting
- * SIDs into the token are enabled for access checks.
- */
- for (RestrictedSidsInToken = 0; RestrictedSidsInToken < AccessToken->RestrictedSidCount; RestrictedSidsInToken++)
- {
- AccessToken->RestrictedSids[RestrictedSidsInToken].Attributes |= (SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY);
- }
-
- /*
- * As we added restricted SIDs into the token, mark
- * it as restricted.
- */
- AccessToken->TokenFlags |= TOKEN_IS_RESTRICTED;
- }
-
/* We've finally filtered the token, return it to the caller */
*FilteredToken = AccessToken;
Status = STATUS_SUCCESS;
@@ -5045,7 +5045,7 @@ SepAdjustGroups(
PAGED_CODE();
- /* Ensure that the token we get is not plain garbage */
+ /* Ensure that the token we get is valid */
ASSERT(Token);
/* Initialize the counters and begin the work */
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3370652dfc2f1d0c37e06…
commit 3370652dfc2f1d0c37e067b31ee37af67a6320c8
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Sun May 22 18:11:18 2022 +0200
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Mon May 23 19:30:35 2022 +0200
[NTOS:SE] Fix locking in SepDuplicateToken() and SepPerformTokenFiltering() (#4523)
Shared locking must be used on the source token as it is accessed for
reading only. This fixes in particular the kmtest SeTokenFiltering that
would hang otherwise on a (wrong) exclusive locking.
- SepPerformTokenFiltering(): Always shared-lock the source token.
Its callers (NtFilterToken and SeFilterToken) just need to sanitize and
put the parameters in correct form before calling this helper function.
- Sync comments in NtFilterToken() with SeFilterToken().
---
ntoskrnl/se/token.c | 66 +++++++++++++++++++++++------------------------------
1 file changed, 28 insertions(+), 38 deletions(-)
diff --git a/ntoskrnl/se/token.c b/ntoskrnl/se/token.c
index 96e972f2c5b..aad1321abd6 100644
--- a/ntoskrnl/se/token.c
+++ b/ntoskrnl/se/token.c
@@ -1059,7 +1059,7 @@ SepDuplicateToken(
AccessToken->OriginatingLogonSession = Token->OriginatingLogonSession;
/* Lock the source token and copy the mutable fields */
- SepAcquireTokenLockExclusive(Token);
+ SepAcquireTokenLockShared(Token);
AccessToken->SessionId = Token->SessionId;
RtlCopyLuid(&AccessToken->ModifiedId, &Token->ModifiedId);
@@ -1286,23 +1286,20 @@ SepDuplicateToken(
Token->DefaultDacl->AclSize);
}
- /* Unlock the source token */
- SepReleaseTokenLock(Token);
-
- /* Return the token */
+ /* Return the token to the caller */
*NewAccessToken = AccessToken;
Status = STATUS_SUCCESS;
Quit:
if (!NT_SUCCESS(Status))
{
- /* Unlock the source token */
- SepReleaseTokenLock(Token);
-
/* Dereference the token, the delete procedure will clean it up */
ObDereferenceObject(AccessToken);
}
+ /* Unlock the source token */
+ SepReleaseTokenLock(Token);
+
return Status;
}
@@ -2086,8 +2083,8 @@ SepPerformTokenFiltering(
_In_ KPROCESSOR_MODE PreviousMode,
_Out_ PTOKEN *FilteredToken)
{
- PTOKEN AccessToken;
NTSTATUS Status;
+ PTOKEN AccessToken;
PVOID EndMem;
ULONG RestrictedSidsLength;
ULONG PrivilegesLength;
@@ -2100,10 +2097,12 @@ SepPerformTokenFiltering(
BOOLEAN WantPrivilegesDisabled;
BOOLEAN FoundPrivilege;
BOOLEAN FoundGroup;
+
PAGED_CODE();
- /* Ensure that the token we get is not garbage */
+ /* Ensure that the source token is valid, and lock it */
ASSERT(Token);
+ SepAcquireTokenLockShared(Token);
/* Assume the caller doesn't want privileges disabled */
WantPrivilegesDisabled = FALSE;
@@ -2159,6 +2158,9 @@ SepPerformTokenFiltering(
if (!NT_SUCCESS(Status))
{
DPRINT1("SepPerformTokenFiltering(): Failed to create the filtered token object (Status 0x%lx)\n", Status);
+
+ /* Unlock the source token and bail out */
+ SepReleaseTokenLock(Token);
return Status;
}
@@ -2168,10 +2170,7 @@ SepPerformTokenFiltering(
/* Set up a lock for the new token */
Status = SepCreateTokenLock(AccessToken);
if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(AccessToken);
- return Status;
- }
+ goto Quit;
/* Allocate new IDs for the token */
ExAllocateLocallyUniqueId(&AccessToken->TokenId);
@@ -2576,7 +2575,7 @@ SepPerformTokenFiltering(
AccessToken->TokenFlags |= TOKEN_IS_RESTRICTED;
}
- /* We've finally filtered the token, give it to the caller */
+ /* We've finally filtered the token, return it to the caller */
*FilteredToken = AccessToken;
Status = STATUS_SUCCESS;
DPRINT("SepPerformTokenFiltering(): The token has been filtered!\n");
@@ -2584,10 +2583,13 @@ SepPerformTokenFiltering(
Quit:
if (!NT_SUCCESS(Status))
{
- /* Dereference the token */
+ /* Dereference the created token */
ObDereferenceObject(AccessToken);
}
+ /* Unlock the source token */
+ SepReleaseTokenLock(Token);
+
return Status;
}
@@ -2903,12 +2905,6 @@ SepCreateSystemAnonymousLogonTokenNoEveryone(VOID)
* operations and that the access token has been filtered. STATUS_INVALID_PARAMETER
* is returned if one or more of the parameter are not valid. A failure NTSTATUS code
* is returned otherwise.
- *
- * @remarks
- * WARNING -- The caller IS RESPONSIBLE for locking the existing access token
- * before attempting to do any kind of filtering operation into
- * the token. The lock MUST BE RELEASED after this kernel routine
- * has finished doing its work.
*/
NTSTATUS
NTAPI
@@ -2925,6 +2921,7 @@ SeFilterToken(
ULONG PrivilegesCount = 0;
ULONG SidsCount = 0;
ULONG RestrictedSidsCount = 0;
+
PAGED_CODE();
/* Begin copying the counters */
@@ -2969,11 +2966,11 @@ SeFilterToken(
NULL);
if (!NT_SUCCESS(Status))
{
- DPRINT1("SeFilterToken(): Failed to insert the token (Status 0x%lx)\n", Status);
+ DPRINT1("SeFilterToken(): Failed to insert the filtered token (Status 0x%lx)\n", Status);
return Status;
}
- /* Give it to the caller */
+ /* Return it to the caller */
*FilteredToken = AccessToken;
return Status;
}
@@ -6661,7 +6658,7 @@ NtFilterToken(
}
_SEH2_END;
- /* Reference the token and do the job */
+ /* Reference the token */
Status = ObReferenceObjectByHandle(ExistingTokenHandle,
TOKEN_DUPLICATE,
SeTokenObjectType,
@@ -6674,9 +6671,6 @@ NtFilterToken(
return Status;
}
- /* Lock the token */
- SepAcquireTokenLockExclusive(Token);
-
/* Capture the group SIDs */
if (SidsToDisable != NULL)
{
@@ -6734,7 +6728,7 @@ NtFilterToken(
}
}
- /* Call the internal API so that it can filter the token for us */
+ /* Call the internal API */
Status = SepPerformTokenFiltering(Token,
CapturedPrivileges,
CapturedSids,
@@ -6751,7 +6745,7 @@ NtFilterToken(
goto Quit;
}
- /* We got our filtered token, insert it to the handle */
+ /* Insert the filtered token and retrieve a handle to it */
Status = ObInsertObject(FilteredToken,
NULL,
HandleInfo.GrantedAccess,
@@ -6760,11 +6754,11 @@ NtFilterToken(
&FilteredTokenHandle);
if (!NT_SUCCESS(Status))
{
- DPRINT1("NtFilterToken(): Failed to insert the filtered token object into the handle (Status 0x%lx)\n", Status);
+ DPRINT1("NtFilterToken(): Failed to insert the filtered token (Status 0x%lx)\n", Status);
goto Quit;
}
- /* And give it to the caller once we're done */
+ /* And return it to the caller once we're done */
_SEH2_TRY
{
*NewTokenHandle = FilteredTokenHandle;
@@ -6777,17 +6771,15 @@ NtFilterToken(
_SEH2_END;
Quit:
- /* Unlock and dereference the token */
- SepReleaseTokenLock(Token);
+ /* Dereference the token */
ObDereferenceObject(Token);
- /* Release all the stuff we've captured */
+ /* Release all the captured data */
if (CapturedSids != NULL)
{
SeReleaseSidAndAttributesArray(CapturedSids,
PreviousMode,
TRUE);
- CapturedSids = NULL;
}
if (CapturedPrivileges != NULL)
@@ -6795,7 +6787,6 @@ Quit:
SeReleaseLuidAndAttributesArray(CapturedPrivileges,
PreviousMode,
TRUE);
- CapturedPrivileges = NULL;
}
if (CapturedRestrictedSids != NULL)
@@ -6803,7 +6794,6 @@ Quit:
SeReleaseSidAndAttributesArray(CapturedRestrictedSids,
PreviousMode,
TRUE);
- CapturedRestrictedSids = NULL;
}
return Status;