diff --git a/ntoskrnl/ps/security.c b/ntoskrnl/ps/security.c index f696d0f3e51..e245dde563f 100644 --- a/ntoskrnl/ps/security.c +++ b/ntoskrnl/ps/security.c @@ -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; } } @@ -314,7 +328,7 @@ PspSetPrimaryToken(IN PEPROCESS Process, } /* Dereference the token */ - if (TokenHandle) ObDereferenceObject(NewToken); + if (!Token) ObDereferenceObject(NewToken); return Status; }