[NTOSKRNL]

NtAccessCheck: Call SePrivilegePolicyCheck to get the list of required privileges and return it to the caller.
This fixes the ERROR_INSUFFICIENT_BUFFER failures in the advapi32 security winetest.

svn path=/trunk/; revision=75028
This commit is contained in:
Eric Kohl 2017-06-13 20:58:10 +00:00
parent 74a68e0f6b
commit 7b4db04803

View file

@ -316,6 +316,19 @@ SepGetSDGroup(IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
return Group;
}
static
ULONG
SepGetPrivilegeSetLength(IN PPRIVILEGE_SET PrivilegeSet)
{
if (PrivilegeSet == NULL)
return 0;
if (PrivilegeSet->PrivilegeCount == 0)
return (ULONG)(sizeof(PRIVILEGE_SET) - sizeof(LUID_AND_ATTRIBUTES));
return (ULONG)(sizeof(PRIVILEGE_SET) +
(PrivilegeSet->PrivilegeCount - 1) * sizeof(LUID_AND_ATTRIBUTES));
}
/* PUBLIC FUNCTIONS ***********************************************************/
@ -526,6 +539,8 @@ NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
ACCESS_MASK PreviouslyGrantedAccess = 0;
PPRIVILEGE_SET Privileges = NULL;
ULONG CapturedPrivilegeSetLength, RequiredPrivilegeSetLength;
PTOKEN Token;
NTSTATUS Status;
PAGED_CODE();
@ -561,8 +576,8 @@ NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
ProbeForWrite(GrantedAccess, sizeof(ACCESS_MASK), sizeof(ULONG));
ProbeForWrite(AccessStatus, sizeof(NTSTATUS), sizeof(ULONG));
/* Initialize the privilege set */
PrivilegeSet->PrivilegeCount = 0;
/* Capture the privilege set length and the mapping */
CapturedPrivilegeSetLength = *PrivilegeSetLength;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
@ -604,6 +619,64 @@ NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
return STATUS_BAD_IMPERSONATION_LEVEL;
}
/* Check for ACCESS_SYSTEM_SECURITY and WRITE_OWNER access */
Status = SePrivilegePolicyCheck(&DesiredAccess,
&PreviouslyGrantedAccess,
NULL,
Token,
&Privileges,
PreviousMode);
if (!NT_SUCCESS(Status))
{
DPRINT("SePrivilegePolicyCheck failed (Status 0x%08lx)\n", Status);
ObDereferenceObject(Token);
*AccessStatus = Status;
*GrantedAccess = 0;
return STATUS_SUCCESS;
}
/* Check the size of the privilege set and return the privileges */
if (Privileges != NULL)
{
DPRINT("Privileges != NULL\n");
/* Calculate the required privilege set buffer size */
RequiredPrivilegeSetLength = SepGetPrivilegeSetLength(Privileges);
/* Fail if the privilege set buffer is too small */
if (CapturedPrivilegeSetLength < RequiredPrivilegeSetLength)
{
ObDereferenceObject(Token);
SeFreePrivileges(Privileges);
*PrivilegeSetLength = RequiredPrivilegeSetLength;
return STATUS_BUFFER_TOO_SMALL;
}
/* Copy the privilege set to the caller */
RtlCopyMemory(PrivilegeSet,
Privileges,
RequiredPrivilegeSetLength);
/* Free the local privilege set */
SeFreePrivileges(Privileges);
}
else
{
DPRINT("Privileges == NULL\n");
/* Fail if the privilege set buffer is too small */
if (CapturedPrivilegeSetLength < sizeof(PRIVILEGE_SET))
{
ObDereferenceObject(Token);
*PrivilegeSetLength = sizeof(PRIVILEGE_SET);
return STATUS_BUFFER_TOO_SMALL;
}
/* Initialize the privilege set */
PrivilegeSet->PrivilegeCount = 0;
PrivilegeSet->Control = 0;
}
/* Capture the security descriptor */
Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
PreviousMode,