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 ***********************************************************/
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();
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)
{
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,