Author: ekohl Date: Mon Sep 6 09:51:46 2010 New Revision: 48707
URL: http://svn.reactos.org/svn/reactos?rev=48707&view=rev Log: NtAdjustPrivilegesToken: Probe and capture parameters before use.
See issue #5497 for more details.
Modified: trunk/reactos/ntoskrnl/se/token.c
Modified: trunk/reactos/ntoskrnl/se/token.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/se/token.c?rev=487... ============================================================================== --- trunk/reactos/ntoskrnl/se/token.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/se/token.c [iso-8859-1] Mon Sep 6 09:51:46 2010 @@ -1953,11 +1953,13 @@ OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL, OUT PULONG ReturnLength OPTIONAL) { - // PLUID_AND_ATTRIBUTES Privileges; + PLUID_AND_ATTRIBUTES CapturedPrivileges = NULL; KPROCESSOR_MODE PreviousMode; + ULONG CapturedCount = 0; + ULONG CapturedLength = 0; + ULONG NewStateSize = 0; ULONG PrivilegeCount; PTOKEN Token; - // ULONG Length; ULONG i; ULONG j; ULONG k; @@ -1973,30 +1975,95 @@
DPRINT ("NtAdjustPrivilegesToken() called\n");
- // PrivilegeCount = NewState->PrivilegeCount; PreviousMode = KeGetPreviousMode (); - // SeCaptureLuidAndAttributesArray(NewState->Privileges, - // PrivilegeCount, - // PreviousMode, - // NULL, - // 0, - // NonPagedPool, - // 1, - // &Privileges, - // &Length); - - Status = ObReferenceObjectByHandle (TokenHandle, - TOKEN_ADJUST_PRIVILEGES | (PreviousState != NULL ? TOKEN_QUERY : 0), - SepTokenObjectType, - PreviousMode, - (PVOID*)&Token, - NULL); + if (PreviousMode != KernelMode) + { + _SEH2_TRY + { + /* Probe NewState */ + if (DisableAllPrivileges == FALSE) + { + ProbeForRead(NewState, + sizeof(TOKEN_PRIVILEGES), + sizeof(ULONG)); + + CapturedCount = NewState->PrivilegeCount; + NewStateSize = (ULONG)sizeof(TOKEN_PRIVILEGES) + + ((CapturedCount - ANYSIZE_ARRAY) * (ULONG)sizeof(LUID_AND_ATTRIBUTES)); + + ProbeForRead(NewState, + NewStateSize, + sizeof(ULONG)); + } + + /* Probe PreviousState and ReturnLength */ + if (PreviousState != NULL) + { + ProbeForWrite(PreviousState, + BufferLength, + sizeof(ULONG)); + + ProbeForWrite(ReturnLength, + sizeof(ULONG), + sizeof(ULONG)); + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Return the exception code */ + _SEH2_YIELD(return _SEH2_GetExceptionCode()); + } + _SEH2_END; + } + else + { + if (DisableAllPrivileges == FALSE) + CapturedCount = NewState->PrivilegeCount; + } + + if (DisableAllPrivileges == FALSE) + { + _SEH2_TRY + { + /* Capture the new state array of privileges */ + Status = SeCaptureLuidAndAttributesArray(NewState->Privileges, + CapturedCount, + PreviousMode, + NULL, + 0, + PagedPool, + TRUE, + &CapturedPrivileges, + &CapturedLength); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Return the exception code */ + _SEH2_YIELD(return _SEH2_GetExceptionCode()); + } + _SEH2_END; + + if (!NT_SUCCESS(Status)) + return Status; + } + + /* Reference the token */ + Status = ObReferenceObjectByHandle(TokenHandle, + TOKEN_ADJUST_PRIVILEGES | (PreviousState != NULL ? TOKEN_QUERY : 0), + SepTokenObjectType, + PreviousMode, + (PVOID*)&Token, + NULL); if (!NT_SUCCESS(Status)) { DPRINT1 ("Failed to reference token (Status %lx)\n", Status); - // SeReleaseLuidAndAttributesArray(Privileges, - // PreviousMode, - // 0); + + /* Release the captured privileges */ + if (CapturedPrivileges != NULL) + SeReleaseLuidAndAttributesArray(CapturedPrivileges, + PreviousMode, + TRUE); + return Status; }
@@ -2061,20 +2128,20 @@ Count = 0; for (i = 0; i < Token->PrivilegeCount; i++) { - for (j = 0; j < NewState->PrivilegeCount; j++) - { - if (Token->Privileges[i].Luid.LowPart == NewState->Privileges[j].Luid.LowPart && - Token->Privileges[i].Luid.HighPart == NewState->Privileges[j].Luid.HighPart) + for (j = 0; j < CapturedCount; j++) + { + if (Token->Privileges[i].Luid.LowPart == CapturedPrivileges[j].Luid.LowPart && + Token->Privileges[i].Luid.HighPart == CapturedPrivileges[j].Luid.HighPart) { DPRINT ("Found privilege\n");
if ((Token->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED) != - (NewState->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED)) + (CapturedPrivileges[j].Attributes & SE_PRIVILEGE_ENABLED)) { DPRINT ("Attributes differ\n"); DPRINT ("Current attributes %lx desired attributes %lx\n", Token->Privileges[i].Attributes, - NewState->Privileges[j].Attributes); + CapturedPrivileges[j].Attributes);
/* Save current privilege */ if (PreviousState != NULL) @@ -2100,7 +2167,7 @@ /* Update current privlege */ Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED; Token->Privileges[i].Attributes |= - (NewState->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED); + (CapturedPrivileges[j].Attributes & SE_PRIVILEGE_ENABLED); DPRINT ("New attributes %lx\n", Token->Privileges[i].Attributes); } @@ -2110,7 +2177,7 @@ } }
- Status = Count < NewState->PrivilegeCount ? STATUS_NOT_ALL_ASSIGNED : STATUS_SUCCESS; + Status = Count < CapturedCount ? STATUS_NOT_ALL_ASSIGNED : STATUS_SUCCESS; }
if (ReturnLength != NULL) @@ -2119,11 +2186,14 @@ (sizeof(LUID_AND_ATTRIBUTES) * (k - 1)); }
+ /* Dereference the token */ ObDereferenceObject (Token);
- // SeReleaseLuidAndAttributesArray(Privileges, - // PreviousMode, - // 0); + /* Release the captured privileges */ + if (CapturedPrivileges != NULL) + SeReleaseLuidAndAttributesArray(CapturedPrivileges, + PreviousMode, + TRUE);
DPRINT ("NtAdjustPrivilegesToken() done\n");