mirror of
https://github.com/reactos/reactos.git
synced 2025-04-27 09:00:27 +00:00
[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().
This commit is contained in:
parent
b33911b93d
commit
3370652dfc
1 changed files with 28 additions and 38 deletions
|
@ -1059,7 +1059,7 @@ SepDuplicateToken(
|
||||||
AccessToken->OriginatingLogonSession = Token->OriginatingLogonSession;
|
AccessToken->OriginatingLogonSession = Token->OriginatingLogonSession;
|
||||||
|
|
||||||
/* Lock the source token and copy the mutable fields */
|
/* Lock the source token and copy the mutable fields */
|
||||||
SepAcquireTokenLockExclusive(Token);
|
SepAcquireTokenLockShared(Token);
|
||||||
|
|
||||||
AccessToken->SessionId = Token->SessionId;
|
AccessToken->SessionId = Token->SessionId;
|
||||||
RtlCopyLuid(&AccessToken->ModifiedId, &Token->ModifiedId);
|
RtlCopyLuid(&AccessToken->ModifiedId, &Token->ModifiedId);
|
||||||
|
@ -1286,23 +1286,20 @@ SepDuplicateToken(
|
||||||
Token->DefaultDacl->AclSize);
|
Token->DefaultDacl->AclSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unlock the source token */
|
/* Return the token to the caller */
|
||||||
SepReleaseTokenLock(Token);
|
|
||||||
|
|
||||||
/* Return the token */
|
|
||||||
*NewAccessToken = AccessToken;
|
*NewAccessToken = AccessToken;
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
Quit:
|
Quit:
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
/* Unlock the source token */
|
|
||||||
SepReleaseTokenLock(Token);
|
|
||||||
|
|
||||||
/* Dereference the token, the delete procedure will clean it up */
|
/* Dereference the token, the delete procedure will clean it up */
|
||||||
ObDereferenceObject(AccessToken);
|
ObDereferenceObject(AccessToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Unlock the source token */
|
||||||
|
SepReleaseTokenLock(Token);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2086,8 +2083,8 @@ SepPerformTokenFiltering(
|
||||||
_In_ KPROCESSOR_MODE PreviousMode,
|
_In_ KPROCESSOR_MODE PreviousMode,
|
||||||
_Out_ PTOKEN *FilteredToken)
|
_Out_ PTOKEN *FilteredToken)
|
||||||
{
|
{
|
||||||
PTOKEN AccessToken;
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
PTOKEN AccessToken;
|
||||||
PVOID EndMem;
|
PVOID EndMem;
|
||||||
ULONG RestrictedSidsLength;
|
ULONG RestrictedSidsLength;
|
||||||
ULONG PrivilegesLength;
|
ULONG PrivilegesLength;
|
||||||
|
@ -2100,10 +2097,12 @@ SepPerformTokenFiltering(
|
||||||
BOOLEAN WantPrivilegesDisabled;
|
BOOLEAN WantPrivilegesDisabled;
|
||||||
BOOLEAN FoundPrivilege;
|
BOOLEAN FoundPrivilege;
|
||||||
BOOLEAN FoundGroup;
|
BOOLEAN FoundGroup;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
/* Ensure that the token we get is not garbage */
|
/* Ensure that the source token is valid, and lock it */
|
||||||
ASSERT(Token);
|
ASSERT(Token);
|
||||||
|
SepAcquireTokenLockShared(Token);
|
||||||
|
|
||||||
/* Assume the caller doesn't want privileges disabled */
|
/* Assume the caller doesn't want privileges disabled */
|
||||||
WantPrivilegesDisabled = FALSE;
|
WantPrivilegesDisabled = FALSE;
|
||||||
|
@ -2159,6 +2158,9 @@ SepPerformTokenFiltering(
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT1("SepPerformTokenFiltering(): Failed to create the filtered token object (Status 0x%lx)\n", 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;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2168,10 +2170,7 @@ SepPerformTokenFiltering(
|
||||||
/* Set up a lock for the new token */
|
/* Set up a lock for the new token */
|
||||||
Status = SepCreateTokenLock(AccessToken);
|
Status = SepCreateTokenLock(AccessToken);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
goto Quit;
|
||||||
ObDereferenceObject(AccessToken);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate new IDs for the token */
|
/* Allocate new IDs for the token */
|
||||||
ExAllocateLocallyUniqueId(&AccessToken->TokenId);
|
ExAllocateLocallyUniqueId(&AccessToken->TokenId);
|
||||||
|
@ -2576,7 +2575,7 @@ SepPerformTokenFiltering(
|
||||||
AccessToken->TokenFlags |= TOKEN_IS_RESTRICTED;
|
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;
|
*FilteredToken = AccessToken;
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
DPRINT("SepPerformTokenFiltering(): The token has been filtered!\n");
|
DPRINT("SepPerformTokenFiltering(): The token has been filtered!\n");
|
||||||
|
@ -2584,10 +2583,13 @@ SepPerformTokenFiltering(
|
||||||
Quit:
|
Quit:
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
/* Dereference the token */
|
/* Dereference the created token */
|
||||||
ObDereferenceObject(AccessToken);
|
ObDereferenceObject(AccessToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Unlock the source token */
|
||||||
|
SepReleaseTokenLock(Token);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2903,12 +2905,6 @@ SepCreateSystemAnonymousLogonTokenNoEveryone(VOID)
|
||||||
* operations and that the access token has been filtered. STATUS_INVALID_PARAMETER
|
* 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 if one or more of the parameter are not valid. A failure NTSTATUS code
|
||||||
* is returned otherwise.
|
* 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
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
|
@ -2925,6 +2921,7 @@ SeFilterToken(
|
||||||
ULONG PrivilegesCount = 0;
|
ULONG PrivilegesCount = 0;
|
||||||
ULONG SidsCount = 0;
|
ULONG SidsCount = 0;
|
||||||
ULONG RestrictedSidsCount = 0;
|
ULONG RestrictedSidsCount = 0;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
/* Begin copying the counters */
|
/* Begin copying the counters */
|
||||||
|
@ -2969,11 +2966,11 @@ SeFilterToken(
|
||||||
NULL);
|
NULL);
|
||||||
if (!NT_SUCCESS(Status))
|
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;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Give it to the caller */
|
/* Return it to the caller */
|
||||||
*FilteredToken = AccessToken;
|
*FilteredToken = AccessToken;
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
@ -6661,7 +6658,7 @@ NtFilterToken(
|
||||||
}
|
}
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
|
|
||||||
/* Reference the token and do the job */
|
/* Reference the token */
|
||||||
Status = ObReferenceObjectByHandle(ExistingTokenHandle,
|
Status = ObReferenceObjectByHandle(ExistingTokenHandle,
|
||||||
TOKEN_DUPLICATE,
|
TOKEN_DUPLICATE,
|
||||||
SeTokenObjectType,
|
SeTokenObjectType,
|
||||||
|
@ -6674,9 +6671,6 @@ NtFilterToken(
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lock the token */
|
|
||||||
SepAcquireTokenLockExclusive(Token);
|
|
||||||
|
|
||||||
/* Capture the group SIDs */
|
/* Capture the group SIDs */
|
||||||
if (SidsToDisable != NULL)
|
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,
|
Status = SepPerformTokenFiltering(Token,
|
||||||
CapturedPrivileges,
|
CapturedPrivileges,
|
||||||
CapturedSids,
|
CapturedSids,
|
||||||
|
@ -6751,7 +6745,7 @@ NtFilterToken(
|
||||||
goto Quit;
|
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,
|
Status = ObInsertObject(FilteredToken,
|
||||||
NULL,
|
NULL,
|
||||||
HandleInfo.GrantedAccess,
|
HandleInfo.GrantedAccess,
|
||||||
|
@ -6760,11 +6754,11 @@ NtFilterToken(
|
||||||
&FilteredTokenHandle);
|
&FilteredTokenHandle);
|
||||||
if (!NT_SUCCESS(Status))
|
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;
|
goto Quit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* And give it to the caller once we're done */
|
/* And return it to the caller once we're done */
|
||||||
_SEH2_TRY
|
_SEH2_TRY
|
||||||
{
|
{
|
||||||
*NewTokenHandle = FilteredTokenHandle;
|
*NewTokenHandle = FilteredTokenHandle;
|
||||||
|
@ -6777,17 +6771,15 @@ NtFilterToken(
|
||||||
_SEH2_END;
|
_SEH2_END;
|
||||||
|
|
||||||
Quit:
|
Quit:
|
||||||
/* Unlock and dereference the token */
|
/* Dereference the token */
|
||||||
SepReleaseTokenLock(Token);
|
|
||||||
ObDereferenceObject(Token);
|
ObDereferenceObject(Token);
|
||||||
|
|
||||||
/* Release all the stuff we've captured */
|
/* Release all the captured data */
|
||||||
if (CapturedSids != NULL)
|
if (CapturedSids != NULL)
|
||||||
{
|
{
|
||||||
SeReleaseSidAndAttributesArray(CapturedSids,
|
SeReleaseSidAndAttributesArray(CapturedSids,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
TRUE);
|
TRUE);
|
||||||
CapturedSids = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CapturedPrivileges != NULL)
|
if (CapturedPrivileges != NULL)
|
||||||
|
@ -6795,7 +6787,6 @@ Quit:
|
||||||
SeReleaseLuidAndAttributesArray(CapturedPrivileges,
|
SeReleaseLuidAndAttributesArray(CapturedPrivileges,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
TRUE);
|
TRUE);
|
||||||
CapturedPrivileges = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CapturedRestrictedSids != NULL)
|
if (CapturedRestrictedSids != NULL)
|
||||||
|
@ -6803,7 +6794,6 @@ Quit:
|
||||||
SeReleaseSidAndAttributesArray(CapturedRestrictedSids,
|
SeReleaseSidAndAttributesArray(CapturedRestrictedSids,
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
TRUE);
|
TRUE);
|
||||||
CapturedRestrictedSids = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
|
|
Loading…
Reference in a new issue