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=48…
==============================================================================
--- 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");