NtAdjustPrivilegesToken: Probe and capture parameters before use.

See issue #5497 for more details.

svn path=/trunk/; revision=48707
This commit is contained in:
Eric Kohl 2010-09-06 09:51:46 +00:00
parent 3995cce1ba
commit b9159984e7

View file

@ -1953,11 +1953,13 @@ NtAdjustPrivilegesToken(IN HANDLE TokenHandle,
OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL, OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL,
OUT PULONG ReturnLength OPTIONAL) OUT PULONG ReturnLength OPTIONAL)
{ {
// PLUID_AND_ATTRIBUTES Privileges; PLUID_AND_ATTRIBUTES CapturedPrivileges = NULL;
KPROCESSOR_MODE PreviousMode; KPROCESSOR_MODE PreviousMode;
ULONG CapturedCount = 0;
ULONG CapturedLength = 0;
ULONG NewStateSize = 0;
ULONG PrivilegeCount; ULONG PrivilegeCount;
PTOKEN Token; PTOKEN Token;
// ULONG Length;
ULONG i; ULONG i;
ULONG j; ULONG j;
ULONG k; ULONG k;
@ -1973,30 +1975,95 @@ NtAdjustPrivilegesToken(IN HANDLE TokenHandle,
DPRINT ("NtAdjustPrivilegesToken() called\n"); DPRINT ("NtAdjustPrivilegesToken() called\n");
// PrivilegeCount = NewState->PrivilegeCount;
PreviousMode = KeGetPreviousMode (); PreviousMode = KeGetPreviousMode ();
// SeCaptureLuidAndAttributesArray(NewState->Privileges, if (PreviousMode != KernelMode)
// PrivilegeCount, {
// PreviousMode, _SEH2_TRY
// NULL, {
// 0, /* Probe NewState */
// NonPagedPool, if (DisableAllPrivileges == FALSE)
// 1, {
// &Privileges, ProbeForRead(NewState,
// &Length); sizeof(TOKEN_PRIVILEGES),
sizeof(ULONG));
Status = ObReferenceObjectByHandle (TokenHandle, CapturedCount = NewState->PrivilegeCount;
TOKEN_ADJUST_PRIVILEGES | (PreviousState != NULL ? TOKEN_QUERY : 0), NewStateSize = (ULONG)sizeof(TOKEN_PRIVILEGES) +
SepTokenObjectType, ((CapturedCount - ANYSIZE_ARRAY) * (ULONG)sizeof(LUID_AND_ATTRIBUTES));
PreviousMode,
(PVOID*)&Token, ProbeForRead(NewState,
NULL); 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)) if (!NT_SUCCESS(Status))
{ {
DPRINT1 ("Failed to reference token (Status %lx)\n", Status); DPRINT1 ("Failed to reference token (Status %lx)\n", Status);
// SeReleaseLuidAndAttributesArray(Privileges,
// PreviousMode, /* Release the captured privileges */
// 0); if (CapturedPrivileges != NULL)
SeReleaseLuidAndAttributesArray(CapturedPrivileges,
PreviousMode,
TRUE);
return Status; return Status;
} }
@ -2061,20 +2128,20 @@ NtAdjustPrivilegesToken(IN HANDLE TokenHandle,
Count = 0; Count = 0;
for (i = 0; i < Token->PrivilegeCount; i++) for (i = 0; i < Token->PrivilegeCount; i++)
{ {
for (j = 0; j < NewState->PrivilegeCount; j++) for (j = 0; j < CapturedCount; j++)
{ {
if (Token->Privileges[i].Luid.LowPart == NewState->Privileges[j].Luid.LowPart && if (Token->Privileges[i].Luid.LowPart == CapturedPrivileges[j].Luid.LowPart &&
Token->Privileges[i].Luid.HighPart == NewState->Privileges[j].Luid.HighPart) Token->Privileges[i].Luid.HighPart == CapturedPrivileges[j].Luid.HighPart)
{ {
DPRINT ("Found privilege\n"); DPRINT ("Found privilege\n");
if ((Token->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED) != 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 ("Attributes differ\n");
DPRINT ("Current attributes %lx desired attributes %lx\n", DPRINT ("Current attributes %lx desired attributes %lx\n",
Token->Privileges[i].Attributes, Token->Privileges[i].Attributes,
NewState->Privileges[j].Attributes); CapturedPrivileges[j].Attributes);
/* Save current privilege */ /* Save current privilege */
if (PreviousState != NULL) if (PreviousState != NULL)
@ -2100,7 +2167,7 @@ NtAdjustPrivilegesToken(IN HANDLE TokenHandle,
/* Update current privlege */ /* Update current privlege */
Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED; Token->Privileges[i].Attributes &= ~SE_PRIVILEGE_ENABLED;
Token->Privileges[i].Attributes |= Token->Privileges[i].Attributes |=
(NewState->Privileges[j].Attributes & SE_PRIVILEGE_ENABLED); (CapturedPrivileges[j].Attributes & SE_PRIVILEGE_ENABLED);
DPRINT ("New attributes %lx\n", DPRINT ("New attributes %lx\n",
Token->Privileges[i].Attributes); Token->Privileges[i].Attributes);
} }
@ -2110,7 +2177,7 @@ NtAdjustPrivilegesToken(IN HANDLE TokenHandle,
} }
} }
Status = Count < NewState->PrivilegeCount ? STATUS_NOT_ALL_ASSIGNED : STATUS_SUCCESS; Status = Count < CapturedCount ? STATUS_NOT_ALL_ASSIGNED : STATUS_SUCCESS;
} }
if (ReturnLength != NULL) if (ReturnLength != NULL)
@ -2119,11 +2186,14 @@ NtAdjustPrivilegesToken(IN HANDLE TokenHandle,
(sizeof(LUID_AND_ATTRIBUTES) * (k - 1)); (sizeof(LUID_AND_ATTRIBUTES) * (k - 1));
} }
/* Dereference the token */
ObDereferenceObject (Token); ObDereferenceObject (Token);
// SeReleaseLuidAndAttributesArray(Privileges, /* Release the captured privileges */
// PreviousMode, if (CapturedPrivileges != NULL)
// 0); SeReleaseLuidAndAttributesArray(CapturedPrivileges,
PreviousMode,
TRUE);
DPRINT ("NtAdjustPrivilegesToken() done\n"); DPRINT ("NtAdjustPrivilegesToken() done\n");