Author: ekohl
Date: Tue Jun 13 20:58:10 2017
New Revision: 75028
URL:
http://svn.reactos.org/svn/reactos?rev=75028&view=rev
Log:
[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.
Modified:
trunk/reactos/ntoskrnl/se/accesschk.c
Modified: trunk/reactos/ntoskrnl/se/accesschk.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/se/accesschk.c?re…
==============================================================================
--- trunk/reactos/ntoskrnl/se/accesschk.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/se/accesschk.c [iso-8859-1] Tue Jun 13 20:58:10 2017
@@ -316,6 +316,19 @@
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 @@
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 @@
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)
{
@@ -602,6 +617,64 @@
DPRINT("Impersonation level < SecurityIdentification\n");
ObDereferenceObject(Token);
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 */