Author: tkreuzer
Date: Sun Feb 5 17:57:34 2012
New Revision: 55437
URL:
http://svn.reactos.org/svn/reactos?rev=55437&view=rev
Log:
[NTOSKRNL]
- Rewrite SeCaptureSecurityDescriptor. The old code was mess and totally broken for 64
bit.
- Many fixes to security descriptor code that was making wrong assumptions about the
SECURITY_DESCRIPTOR structures
Modified:
trunk/reactos/ntoskrnl/se/sd.c
Modified: trunk/reactos/ntoskrnl/se/sd.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/se/sd.c?rev=55437…
==============================================================================
--- trunk/reactos/ntoskrnl/se/sd.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/se/sd.c [iso-8859-1] Sun Feb 5 17:57:34 2012
@@ -28,6 +28,78 @@
/* PRIVATE FUNCTIONS **********************************************************/
+PSID
+FORCEINLINE
+SepGetGroupFromDescriptor(PVOID _Descriptor)
+{
+ PISECURITY_DESCRIPTOR Descriptor = (PISECURITY_DESCRIPTOR)_Descriptor;
+ PISECURITY_DESCRIPTOR_RELATIVE SdRel;
+
+ if (Descriptor->Control & SE_SELF_RELATIVE)
+ {
+ SdRel = (PISECURITY_DESCRIPTOR_RELATIVE)Descriptor;
+ return (PSID)((ULONG_PTR)Descriptor + SdRel->Group);
+ }
+ else
+ {
+ return Descriptor->Group;
+ }
+}
+
+PSID
+FORCEINLINE
+SepGetOwnerFromDescriptor(PVOID _Descriptor)
+{
+ PISECURITY_DESCRIPTOR Descriptor = (PISECURITY_DESCRIPTOR)_Descriptor;
+ PISECURITY_DESCRIPTOR_RELATIVE SdRel;
+
+ if (Descriptor->Control & SE_SELF_RELATIVE)
+ {
+ SdRel = (PISECURITY_DESCRIPTOR_RELATIVE)Descriptor;
+ return (PSID)((ULONG_PTR)Descriptor + SdRel->Owner);
+ }
+ else
+ {
+ return Descriptor->Owner;
+ }
+}
+
+PACL
+FORCEINLINE
+SepGetDaclFromDescriptor(PVOID _Descriptor)
+{
+ PISECURITY_DESCRIPTOR Descriptor = (PISECURITY_DESCRIPTOR)_Descriptor;
+ PISECURITY_DESCRIPTOR_RELATIVE SdRel;
+
+ if (Descriptor->Control & SE_SELF_RELATIVE)
+ {
+ SdRel = (PISECURITY_DESCRIPTOR_RELATIVE)Descriptor;
+ return (PACL)((ULONG_PTR)Descriptor + SdRel->Dacl);
+ }
+ else
+ {
+ return Descriptor->Dacl;
+ }
+}
+
+PACL
+FORCEINLINE
+SepGetSaclFromDescriptor(PVOID _Descriptor)
+{
+ PISECURITY_DESCRIPTOR Descriptor = (PISECURITY_DESCRIPTOR)_Descriptor;
+ PISECURITY_DESCRIPTOR_RELATIVE SdRel;
+
+ if (Descriptor->Control & SE_SELF_RELATIVE)
+ {
+ SdRel = (PISECURITY_DESCRIPTOR_RELATIVE)Descriptor;
+ return (PACL)((ULONG_PTR)Descriptor + SdRel->Sacl);
+ }
+ else
+ {
+ return Descriptor->Sacl;
+ }
+}
+
BOOLEAN
INIT_FUNCTION
NTAPI
@@ -120,7 +192,7 @@
PISECURITY_DESCRIPTOR SecurityDescriptor,
PULONG BufferLength)
{
- ULONG_PTR Current;
+ ULONG Current;
ULONG SidSize;
ULONG SdSize;
NTSTATUS Status;
@@ -160,29 +232,25 @@
return Status;
}
- Current = (ULONG_PTR)(SdRel + 1);
+ Current = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
if (SecurityInformation & OWNER_SECURITY_INFORMATION)
{
- RtlCopyMemory((PVOID)Current,
- SeWorldSid,
- SidSize);
- SdRel->Owner = (ULONG)((ULONG_PTR)Current - (ULONG_PTR)SdRel);
+ RtlCopyMemory((PUCHAR)SdRel + Current, SeWorldSid, SidSize);
+ SdRel->Owner = Current;
Current += SidSize;
}
if (SecurityInformation & GROUP_SECURITY_INFORMATION)
{
- RtlCopyMemory((PVOID)Current,
- SeWorldSid,
- SidSize);
- SdRel->Group = (ULONG)((ULONG_PTR)Current - (ULONG_PTR)SdRel);
+ RtlCopyMemory((PUCHAR)SdRel + Current, SeWorldSid, SidSize);
+ SdRel->Group = Current;
Current += SidSize;
}
if (SecurityInformation & DACL_SECURITY_INFORMATION)
{
- PACL Dacl = (PACL)Current;
+ PACL Dacl = (PACL)((PUCHAR)SdRel + Current);
SdRel->Control |= SE_DACL_PRESENT;
Status = RtlCreateAcl(Dacl,
@@ -198,7 +266,7 @@
if (!NT_SUCCESS(Status))
return Status;
- SdRel->Dacl = (ULONG)((ULONG_PTR)Current - (ULONG_PTR)SdRel);
+ SdRel->Dacl = Current;
}
if (SecurityInformation & SACL_SECURITY_INFORMATION)
@@ -245,7 +313,7 @@
ProbeForRead(ObjectAttributes->SecurityQualityOfService,
sizeof(SECURITY_QUALITY_OF_SERVICE),
sizeof(ULONG));
-
+
if
(((PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService)->Length
==
sizeof(SECURITY_QUALITY_OF_SERVICE))
{
@@ -381,335 +449,239 @@
/* PUBLIC FUNCTIONS ***********************************************************/
-/*
- * @implemented
- */
+static
+ULONG
+DetermineSIDSize(
+ PISID Sid,
+ PULONG OutSAC,
+ KPROCESSOR_MODE ProcessorMode)
+{
+ ULONG Size;
+
+ if (!Sid)
+ {
+ *OutSAC = 0;
+ return 0;
+ }
+
+ if (ProcessorMode != KernelMode)
+ {
+ /* Securely access the buffers! */
+ *OutSAC = ProbeForReadUchar(&Sid->SubAuthorityCount);
+ Size = RtlLengthRequiredSid(*OutSAC);
+ ProbeForRead(Sid, Size, sizeof(ULONG));
+ }
+ else
+ {
+ *OutSAC = Sid->SubAuthorityCount;
+ Size = RtlLengthRequiredSid(*OutSAC);
+ }
+
+ return Size;
+}
+
+static
+ULONG
+DetermineACLSize(
+ PACL Acl,
+ KPROCESSOR_MODE ProcessorMode)
+{
+ ULONG Size;
+
+ if (!Acl) return 0;
+
+ if (ProcessorMode == KernelMode) return Acl->AclSize;
+
+ /* Probe the buffers! */
+ Size = ProbeForReadUshort(&Acl->AclSize);
+ ProbeForRead(Acl, Size, sizeof(ULONG));
+
+ return Size;
+}
+
NTSTATUS
NTAPI
-SeCaptureSecurityDescriptor(IN PSECURITY_DESCRIPTOR _OriginalSecurityDescriptor,
- IN KPROCESSOR_MODE CurrentMode,
- IN POOL_TYPE PoolType,
- IN BOOLEAN CaptureIfKernel,
- OUT PSECURITY_DESCRIPTOR *CapturedSecurityDescriptor)
-{
- PISECURITY_DESCRIPTOR OriginalSecurityDescriptor = _OriginalSecurityDescriptor;
+SeCaptureSecurityDescriptor(
+ IN PSECURITY_DESCRIPTOR _OriginalSecurityDescriptor,
+ IN KPROCESSOR_MODE CurrentMode,
+ IN POOL_TYPE PoolType,
+ IN BOOLEAN CaptureIfKernel,
+ OUT PSECURITY_DESCRIPTOR *CapturedSecurityDescriptor)
+{
+ PISECURITY_DESCRIPTOR OriginalDescriptor = _OriginalSecurityDescriptor;
SECURITY_DESCRIPTOR DescriptorCopy;
- PISECURITY_DESCRIPTOR NewDescriptor;
+ PISECURITY_DESCRIPTOR_RELATIVE NewDescriptor;
ULONG OwnerSAC = 0, GroupSAC = 0;
ULONG OwnerSize = 0, GroupSize = 0;
ULONG SaclSize = 0, DaclSize = 0;
ULONG DescriptorSize = 0;
- NTSTATUS Status;
-
- if (OriginalSecurityDescriptor != NULL)
- {
- if (CurrentMode != KernelMode)
- {
- RtlZeroMemory(&DescriptorCopy, sizeof(DescriptorCopy));
-
- _SEH2_TRY
- {
- /*
- * First only probe and copy until the control field of the descriptor
- * to determine whether it's a self-relative descriptor
- */
- DescriptorSize = FIELD_OFFSET(SECURITY_DESCRIPTOR,
- Owner);
- ProbeForRead(OriginalSecurityDescriptor,
- DescriptorSize,
- sizeof(ULONG));
-
- if (OriginalSecurityDescriptor->Revision !=
SECURITY_DESCRIPTOR_REVISION1)
- {
- _SEH2_YIELD(return STATUS_UNKNOWN_REVISION);
- }
-
- /* Make a copy on the stack */
- DescriptorCopy.Revision = OriginalSecurityDescriptor->Revision;
- DescriptorCopy.Sbz1 = OriginalSecurityDescriptor->Sbz1;
- DescriptorCopy.Control = OriginalSecurityDescriptor->Control;
- DescriptorSize = ((DescriptorCopy.Control & SE_SELF_RELATIVE) ?
- sizeof(SECURITY_DESCRIPTOR_RELATIVE) :
sizeof(SECURITY_DESCRIPTOR));
-
- /*
- * Probe and copy the entire security descriptor structure. The SIDs
- * and ACLs will be probed and copied later though
- */
- ProbeForRead(OriginalSecurityDescriptor,
- DescriptorSize,
- sizeof(ULONG));
- if (DescriptorCopy.Control & SE_SELF_RELATIVE)
- {
- PISECURITY_DESCRIPTOR_RELATIVE RelSD =
(PISECURITY_DESCRIPTOR_RELATIVE)OriginalSecurityDescriptor;
-
- DescriptorCopy.Owner = (PSID)RelSD->Owner;
- DescriptorCopy.Group = (PSID)RelSD->Group;
- DescriptorCopy.Sacl = (PACL)RelSD->Sacl;
- DescriptorCopy.Dacl = (PACL)RelSD->Dacl;
- }
- else
- {
- DescriptorCopy.Owner = OriginalSecurityDescriptor->Owner;
- DescriptorCopy.Group = OriginalSecurityDescriptor->Group;
- DescriptorCopy.Sacl = OriginalSecurityDescriptor->Sacl;
- DescriptorCopy.Dacl = OriginalSecurityDescriptor->Dacl;
- }
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- /* Return the exception code */
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
- }
- _SEH2_END;
- }
- else if (!CaptureIfKernel)
- {
- if (OriginalSecurityDescriptor->Revision !=
SECURITY_DESCRIPTOR_REVISION1)
- {
- return STATUS_UNKNOWN_REVISION;
- }
-
- *CapturedSecurityDescriptor = OriginalSecurityDescriptor;
- return STATUS_SUCCESS;
- }
- else
- {
- if (OriginalSecurityDescriptor->Revision !=
SECURITY_DESCRIPTOR_REVISION1)
- {
- return STATUS_UNKNOWN_REVISION;
- }
-
- /* Make a copy on the stack */
- DescriptorCopy.Revision = OriginalSecurityDescriptor->Revision;
- DescriptorCopy.Sbz1 = OriginalSecurityDescriptor->Sbz1;
- DescriptorCopy.Control = OriginalSecurityDescriptor->Control;
- DescriptorSize = ((DescriptorCopy.Control & SE_SELF_RELATIVE) ?
- sizeof(SECURITY_DESCRIPTOR_RELATIVE) :
sizeof(SECURITY_DESCRIPTOR));
- if (DescriptorCopy.Control & SE_SELF_RELATIVE)
- {
- PISECURITY_DESCRIPTOR_RELATIVE RelSD =
(PISECURITY_DESCRIPTOR_RELATIVE)OriginalSecurityDescriptor;
-
- DescriptorCopy.Owner = (PSID)RelSD->Owner;
- DescriptorCopy.Group = (PSID)RelSD->Group;
- DescriptorCopy.Sacl = (PACL)RelSD->Sacl;
- DescriptorCopy.Dacl = (PACL)RelSD->Dacl;
- }
- else
- {
- DescriptorCopy.Owner = OriginalSecurityDescriptor->Owner;
- DescriptorCopy.Group = OriginalSecurityDescriptor->Group;
- DescriptorCopy.Sacl = OriginalSecurityDescriptor->Sacl;
- DescriptorCopy.Dacl = OriginalSecurityDescriptor->Dacl;
- }
- }
-
- if (DescriptorCopy.Control & SE_SELF_RELATIVE)
- {
- /*
- * In case we're dealing with a self-relative descriptor, do a basic
convert
- * to an absolute descriptor. We do this so we can simply access the data
- * using the pointers without calculating them again.
- */
- DescriptorCopy.Control &= ~SE_SELF_RELATIVE;
- if (DescriptorCopy.Owner != NULL)
- {
- DescriptorCopy.Owner = (PSID)((ULONG_PTR)OriginalSecurityDescriptor +
(ULONG_PTR)DescriptorCopy.Owner);
- }
- if (DescriptorCopy.Group != NULL)
- {
- DescriptorCopy.Group = (PSID)((ULONG_PTR)OriginalSecurityDescriptor +
(ULONG_PTR)DescriptorCopy.Group);
- }
- if (DescriptorCopy.Dacl != NULL)
- {
- DescriptorCopy.Dacl = (PACL)((ULONG_PTR)OriginalSecurityDescriptor +
(ULONG_PTR)DescriptorCopy.Dacl);
- }
- if (DescriptorCopy.Sacl != NULL)
- {
- DescriptorCopy.Sacl = (PACL)((ULONG_PTR)OriginalSecurityDescriptor +
(ULONG_PTR)DescriptorCopy.Sacl);
- }
- }
-
- /* Determine the size of the SIDs */
-#define DetermineSIDSize(SidType) \
-do { \
-if(DescriptorCopy.SidType != NULL) \
-{ \
-SID *SidType = (SID*)DescriptorCopy.SidType; \
-\
-if(CurrentMode != KernelMode) \
-{ \
-/* Securely access the buffers! */ \
-_SEH2_TRY \
-{ \
-SidType##SAC = ProbeForReadUchar(&SidType->SubAuthorityCount); \
-SidType##Size = RtlLengthRequiredSid(SidType##SAC); \
-DescriptorSize += ROUND_UP(SidType##Size, sizeof(ULONG)); \
-ProbeForRead(SidType, \
-SidType##Size, \
-sizeof(ULONG)); \
-} \
-_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
\
-{ \
-_SEH2_YIELD(return _SEH2_GetExceptionCode()); \
-} \
-_SEH2_END; \
-\
-} \
-else \
-{ \
-SidType##SAC = SidType->SubAuthorityCount; \
-SidType##Size = RtlLengthRequiredSid(SidType##SAC); \
-DescriptorSize += ROUND_UP(SidType##Size, sizeof(ULONG)); \
-} \
-} \
-} while(0)
-
- DetermineSIDSize(Owner);
- DetermineSIDSize(Group);
-
-#undef DetermineSIDSize
-
- /* Determine the size of the ACLs */
-#define DetermineACLSize(AclType, AclFlag) \
-do { \
-if((DescriptorCopy.Control & SE_##AclFlag##_PRESENT) && \
-DescriptorCopy.AclType != NULL) \
-{ \
-PACL AclType = (PACL)DescriptorCopy.AclType; \
-\
-if(CurrentMode != KernelMode) \
-{ \
-/* Securely access the buffers! */ \
-_SEH2_TRY \
-{ \
-AclType##Size = ProbeForReadUshort(&AclType->AclSize); \
-DescriptorSize += ROUND_UP(AclType##Size, sizeof(ULONG)); \
-ProbeForRead(AclType, \
-AclType##Size, \
-sizeof(ULONG)); \
-} \
-_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
\
-{ \
-_SEH2_YIELD(return _SEH2_GetExceptionCode()); \
-} \
-_SEH2_END; \
-\
-} \
-else \
-{ \
-AclType##Size = AclType->AclSize; \
-DescriptorSize += ROUND_UP(AclType##Size, sizeof(ULONG)); \
-} \
-} \
-else \
-{ \
-DescriptorCopy.AclType = NULL; \
-} \
-} while(0)
-
- DetermineACLSize(Sacl, SACL);
- DetermineACLSize(Dacl, DACL);
-
-#undef DetermineACLSize
-
- /*
- * Allocate enough memory to store a complete copy of a self-relative
- * security descriptor
- */
- NewDescriptor = ExAllocatePoolWithTag(PoolType,
- DescriptorSize,
- TAG_SD);
- if (NewDescriptor != NULL)
- {
- ULONG_PTR Offset = sizeof(SECURITY_DESCRIPTOR);
-
- RtlZeroMemory(NewDescriptor, DescriptorSize);
- NewDescriptor->Revision = DescriptorCopy.Revision;
- NewDescriptor->Sbz1 = DescriptorCopy.Sbz1;
- NewDescriptor->Control = DescriptorCopy.Control | SE_SELF_RELATIVE;
-
- _SEH2_TRY
- {
- /*
- * Setup the offsets and copy the SIDs and ACLs to the new
- * self-relative security descriptor. Probing the pointers is not
- * neccessary anymore as we did that when collecting the sizes!
- * Make sure to validate the SIDs and ACLs *again* as they could have
- * been modified in the meanwhile!
- */
-#define CopySID(Type) \
-do { \
-if(DescriptorCopy.Type != NULL) \
-{ \
-NewDescriptor->Type = (PVOID)Offset; \
-RtlCopyMemory((PVOID)((ULONG_PTR)NewDescriptor + \
-(ULONG_PTR)NewDescriptor->Type), \
-DescriptorCopy.Type, \
-Type##Size); \
-if (!RtlValidSid((PSID)((ULONG_PTR)NewDescriptor + \
-(ULONG_PTR)NewDescriptor->Type))) \
-{ \
-RtlRaiseStatus(STATUS_INVALID_SID); \
-} \
-Offset += ROUND_UP(Type##Size, sizeof(ULONG)); \
-} \
-} while(0)
-
- CopySID(Owner);
- CopySID(Group);
-
-#undef CopySID
-
-#define CopyACL(Type) \
-do { \
-if(DescriptorCopy.Type != NULL) \
-{ \
-NewDescriptor->Type = (PVOID)Offset; \
-RtlCopyMemory((PVOID)((ULONG_PTR)NewDescriptor + \
-(ULONG_PTR)NewDescriptor->Type), \
-DescriptorCopy.Type, \
-Type##Size); \
-if (!RtlValidAcl((PACL)((ULONG_PTR)NewDescriptor + \
-(ULONG_PTR)NewDescriptor->Type))) \
-{ \
-RtlRaiseStatus(STATUS_INVALID_ACL); \
-} \
-Offset += ROUND_UP(Type##Size, sizeof(ULONG)); \
-} \
-} while(0)
-
- CopyACL(Sacl);
- CopyACL(Dacl);
-
-#undef CopyACL
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- /* We failed to copy the data to the new descriptor */
- ExFreePoolWithTag(NewDescriptor, TAG_SD);
- _SEH2_YIELD(return _SEH2_GetExceptionCode());
- }
- _SEH2_END;
-
- /*
- * We're finally done!
- * Copy the pointer to the captured descriptor to to the caller.
- */
- *CapturedSecurityDescriptor = NewDescriptor;
- return STATUS_SUCCESS;
- }
- else
- {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- }
- }
- else
+ ULONG Offset;
+
+ if (!OriginalDescriptor)
{
/* Nothing to do... */
*CapturedSecurityDescriptor = NULL;
- }
-
- return Status;
+ return STATUS_SUCCESS;
+ }
+
+ /* Quick path */
+ if (CurrentMode == KernelMode && !CaptureIfKernel)
+ {
+ /* Check descriptor version */
+ if (OriginalDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
+ {
+ return STATUS_UNKNOWN_REVISION;
+ }
+
+ *CapturedSecurityDescriptor = _OriginalSecurityDescriptor;
+ return STATUS_SUCCESS;
+ }
+
+ _SEH2_TRY
+ {
+ if (CurrentMode != KernelMode)
+ {
+ ProbeForRead(OriginalDescriptor,
+ sizeof(SECURITY_DESCRIPTOR_RELATIVE),
+ sizeof(ULONG));
+ }
+
+ /* Check the descriptor version */
+ if (OriginalDescriptor->Revision != SECURITY_DESCRIPTOR_REVISION1)
+ {
+ _SEH2_YIELD(return STATUS_UNKNOWN_REVISION);
+ }
+
+ if (CurrentMode != KernelMode)
+ {
+ /* Get the size of the descriptor */
+ DescriptorSize = (OriginalDescriptor->Control & SE_SELF_RELATIVE) ?
+ sizeof(SECURITY_DESCRIPTOR_RELATIVE) : sizeof(SECURITY_DESCRIPTOR);
+
+ /* Probe the entire security descriptor structure. The SIDs
+ * and ACLs will be probed and copied later though */
+ ProbeForRead(OriginalDescriptor, DescriptorSize, sizeof(ULONG));
+ }
+
+ /* Now capture all fields and convert to an absolute descriptor */
+ DescriptorCopy.Revision = OriginalDescriptor->Revision;
+ DescriptorCopy.Sbz1 = OriginalDescriptor->Sbz1;
+ DescriptorCopy.Control = OriginalDescriptor->Control & ~SE_SELF_RELATIVE;
+ DescriptorCopy.Owner = SepGetOwnerFromDescriptor(OriginalDescriptor);
+ DescriptorCopy.Group = SepGetGroupFromDescriptor(OriginalDescriptor);
+ DescriptorCopy.Sacl = SepGetSaclFromDescriptor(OriginalDescriptor);
+ DescriptorCopy.Dacl = SepGetDaclFromDescriptor(OriginalDescriptor);
+ DescriptorSize = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
+
+ /* Determine owner and group sizes */
+ OwnerSize = DetermineSIDSize(DescriptorCopy.Owner, &OwnerSAC, CurrentMode);
+ DescriptorSize += ROUND_UP(OwnerSize, sizeof(ULONG));
+ GroupSize = DetermineSIDSize(DescriptorCopy.Group, &GroupSAC, CurrentMode);
+ DescriptorSize += ROUND_UP(GroupSize, sizeof(ULONG));
+
+ /* Determine the size of the ACLs */
+ if (DescriptorCopy.Control & SE_SACL_PRESENT)
+ {
+ /* Get the size and probe if user mode */
+ SaclSize = DetermineACLSize(DescriptorCopy.Sacl, CurrentMode);
+ DescriptorSize += ROUND_UP(SaclSize, sizeof(ULONG));
+ }
+
+ if (DescriptorCopy.Control & SE_DACL_PRESENT)
+ {
+ /* Get the size and probe if user mode */
+ DaclSize = DetermineACLSize(DescriptorCopy.Dacl, CurrentMode);
+ DescriptorSize += ROUND_UP(DaclSize, sizeof(ULONG));
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END
+
+ /*
+ * Allocate enough memory to store a complete copy of a self-relative
+ * security descriptor
+ */
+ NewDescriptor = ExAllocatePoolWithTag(PoolType,
+ DescriptorSize,
+ TAG_SD);
+ if (!NewDescriptor) return STATUS_INSUFFICIENT_RESOURCES;
+
+ RtlZeroMemory(NewDescriptor, DescriptorSize);
+ NewDescriptor->Revision = DescriptorCopy.Revision;
+ NewDescriptor->Sbz1 = DescriptorCopy.Sbz1;
+ NewDescriptor->Control = DescriptorCopy.Control | SE_SELF_RELATIVE;
+
+ _SEH2_TRY
+ {
+ /*
+ * Setup the offsets and copy the SIDs and ACLs to the new
+ * self-relative security descriptor. Probing the pointers is not
+ * neccessary anymore as we did that when collecting the sizes!
+ * Make sure to validate the SIDs and ACLs *again* as they could have
+ * been modified in the meanwhile!
+ */
+ Offset = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
+
+ if (DescriptorCopy.Owner)
+ {
+ if (!RtlValidSid(DescriptorCopy.Owner)) RtlRaiseStatus(STATUS_INVALID_SID);
+ NewDescriptor->Owner = Offset;
+ RtlCopyMemory((PUCHAR)NewDescriptor + Offset,
+ DescriptorCopy.Owner,
+ OwnerSize);
+ Offset += ROUND_UP(OwnerSize, sizeof(ULONG));
+ }
+
+ if (DescriptorCopy.Group)
+ {
+ if (!RtlValidSid(DescriptorCopy.Group)) RtlRaiseStatus(STATUS_INVALID_SID);
+ NewDescriptor->Group = Offset;
+ RtlCopyMemory((PUCHAR)NewDescriptor + Offset,
+ DescriptorCopy.Group,
+ GroupSize);
+ Offset += ROUND_UP(GroupSize, sizeof(ULONG));
+ }
+
+ if (DescriptorCopy.Sacl)
+ {
+ if (!RtlValidAcl(DescriptorCopy.Sacl)) RtlRaiseStatus(STATUS_INVALID_ACL);
+ NewDescriptor->Sacl = Offset;
+ RtlCopyMemory((PUCHAR)NewDescriptor + Offset,
+ DescriptorCopy.Sacl,
+ SaclSize);
+ Offset += ROUND_UP(SaclSize, sizeof(ULONG));
+ }
+
+ if (DescriptorCopy.Dacl)
+ {
+ if (!RtlValidAcl(DescriptorCopy.Dacl)) RtlRaiseStatus(STATUS_INVALID_ACL);
+ NewDescriptor->Dacl = Offset;
+ RtlCopyMemory((PUCHAR)NewDescriptor + Offset,
+ DescriptorCopy.Dacl,
+ DaclSize);
+ Offset += ROUND_UP(DaclSize, sizeof(ULONG));
+ }
+
+ /* Make sure the size was correct */
+ ASSERT(Offset == DescriptorSize);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* We failed to copy the data to the new descriptor */
+ ExFreePoolWithTag(NewDescriptor, TAG_SD);
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+
+ /*
+ * We're finally done!
+ * Copy the pointer to the captured descriptor to to the caller.
+ */
+ *CapturedSecurityDescriptor = NewDescriptor;
+ return STATUS_SUCCESS;
}
/*
@@ -889,9 +861,10 @@
IN POOL_TYPE PoolType,
IN PGENERIC_MAPPING GenericMapping)
{
- PISECURITY_DESCRIPTOR ObjectSd;
- PISECURITY_DESCRIPTOR NewSd;
+ PISECURITY_DESCRIPTOR_RELATIVE ObjectSd;
+ PISECURITY_DESCRIPTOR_RELATIVE NewSd;
PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
+ PISECURITY_DESCRIPTOR_RELATIVE RelSD =
(PISECURITY_DESCRIPTOR_RELATIVE)SecurityDescriptor;
PSID Owner = 0;
PSID Group = 0;
PACL Dacl = 0;
@@ -901,10 +874,11 @@
ULONG DaclLength = 0;
ULONG SaclLength = 0;
ULONG Control = 0;
- ULONG_PTR Current;
+ ULONG Current;
SECURITY_INFORMATION SecurityInformation;
ObjectSd = *ObjectsSecurityDescriptor;
+ ASSERT(ObjectSd->Control & SE_SELF_RELATIVE);
/* The object does not have a security descriptor. */
if (!ObjectSd)
@@ -918,7 +892,7 @@
if (SecurityDescriptor->Owner != NULL)
{
if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
- Owner = (PSID)((ULONG_PTR)SecurityDescriptor->Owner +
+ Owner = (PSID)((ULONG_PTR)RelSD->Owner +
(ULONG_PTR)SecurityDescriptor);
else
Owner = (PSID)SecurityDescriptor->Owner;
@@ -929,7 +903,7 @@
}
else
{
- if (ObjectSd->Owner != NULL)
+ if (ObjectSd->Owner)
{
Owner = (PSID)((ULONG_PTR)ObjectSd->Owner + (ULONG_PTR)ObjectSd);
OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
@@ -937,7 +911,7 @@
Control |= (ObjectSd->Control & SE_OWNER_DEFAULTED);
}
-
+
/* Get group and group size */
if (SecurityInformation & GROUP_SECURITY_INFORMATION)
{
@@ -955,7 +929,7 @@
}
else
{
- if (ObjectSd->Group != NULL)
+ if (ObjectSd->Group)
{
Group = (PSID)((ULONG_PTR)ObjectSd->Group + (ULONG_PTR)ObjectSd);
GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
@@ -983,8 +957,7 @@
}
else
{
- if ((ObjectSd->Control & SE_DACL_PRESENT) &&
- (ObjectSd->Dacl != NULL))
+ if ((ObjectSd->Control & SE_DACL_PRESENT) && (ObjectSd->Dacl))
{
Dacl = (PACL)((ULONG_PTR)ObjectSd->Dacl + (ULONG_PTR)ObjectSd);
DaclLength = ROUND_UP((ULONG)Dacl->AclSize, 4);
@@ -992,7 +965,7 @@
Control |= (ObjectSd->Control & (SE_DACL_DEFAULTED | SE_DACL_PRESENT));
}
-
+
/* Get SACL and SACL size */
if (SecurityInformation & SACL_SECURITY_INFORMATION)
{
@@ -1011,8 +984,7 @@
}
else
{
- if ((ObjectSd->Control & SE_SACL_PRESENT) &&
- (ObjectSd->Sacl != NULL))
+ if ((ObjectSd->Control & SE_SACL_PRESENT) && (ObjectSd->Sacl))
{
Sacl = (PACL)((ULONG_PTR)ObjectSd->Sacl + (ULONG_PTR)ObjectSd);
SaclLength = ROUND_UP((ULONG)Sacl->AclSize, 4);
@@ -1022,7 +994,7 @@
}
NewSd = ExAllocatePool(NonPagedPool,
- sizeof(SECURITY_DESCRIPTOR) + OwnerLength + GroupLength +
+ sizeof(SECURITY_DESCRIPTOR_RELATIVE) + OwnerLength +
GroupLength +
DaclLength + SaclLength);
if (NewSd == NULL)
{
@@ -1036,41 +1008,33 @@
/* We always build a self-relative descriptor */
NewSd->Control = (USHORT)Control | SE_SELF_RELATIVE;
- Current = (ULONG_PTR)NewSd + sizeof(SECURITY_DESCRIPTOR);
+ Current = sizeof(SECURITY_DESCRIPTOR);
if (OwnerLength != 0)
{
- RtlCopyMemory((PVOID)Current,
- Owner,
- OwnerLength);
- NewSd->Owner = (PSID)(Current - (ULONG_PTR)NewSd);
+ RtlCopyMemory((PUCHAR)NewSd + Current, Owner, OwnerLength);
+ NewSd->Owner = Current;
Current += OwnerLength;
}
if (GroupLength != 0)
{
- RtlCopyMemory((PVOID)Current,
- Group,
- GroupLength);
- NewSd->Group = (PSID)(Current - (ULONG_PTR)NewSd);
+ RtlCopyMemory((PUCHAR)NewSd + Current, Group, GroupLength);
+ NewSd->Group = Current;
Current += GroupLength;
}
if (DaclLength != 0)
{
- RtlCopyMemory((PVOID)Current,
- Dacl,
- DaclLength);
- NewSd->Dacl = (PACL)(Current - (ULONG_PTR)NewSd);
+ RtlCopyMemory((PUCHAR)NewSd + Current, Dacl, DaclLength);
+ NewSd->Dacl = Current;
Current += DaclLength;
}
if (SaclLength != 0)
{
- RtlCopyMemory((PVOID)Current,
- Sacl,
- SaclLength);
- NewSd->Sacl = (PACL)(Current - (ULONG_PTR)NewSd);
+ RtlCopyMemory((PUCHAR)NewSd + Current, Sacl, SaclLength);
+ NewSd->Sacl = Current;
Current += SaclLength;
}
@@ -1112,7 +1076,7 @@
ULONG SdLength;
PISID Sid;
PACL Acl;
- PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
+ PISECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor = _SecurityDescriptor;
if (Length < SECURITY_DESCRIPTOR_MIN_LENGTH)
{
@@ -1135,19 +1099,19 @@
SdLength = sizeof(SECURITY_DESCRIPTOR);
/* Check Owner SID */
- if (SecurityDescriptor->Owner == NULL)
+ if (SecurityDescriptor->Owner)
{
DPRINT1("No Owner SID\n");
return FALSE;
}
- if ((ULONG_PTR)SecurityDescriptor->Owner % sizeof(ULONG))
+ if (SecurityDescriptor->Owner % sizeof(ULONG))
{
DPRINT1("Invalid Owner SID alignment\n");
return FALSE;
}
- Sid = (PISID)((ULONG_PTR)SecurityDescriptor +
(ULONG_PTR)SecurityDescriptor->Owner);
+ Sid = (PISID)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Owner);
if (Sid->Revision != SID_REVISION)
{
DPRINT1("Invalid Owner SID revision\n");
@@ -1162,15 +1126,15 @@
}
/* Check Group SID */
- if (SecurityDescriptor->Group != NULL)
- {
- if ((ULONG_PTR)SecurityDescriptor->Group % sizeof(ULONG))
+ if (SecurityDescriptor->Group)
+ {
+ if (SecurityDescriptor->Group % sizeof(ULONG))
{
DPRINT1("Invalid Group SID alignment\n");
return FALSE;
}
- Sid = (PSID)((ULONG_PTR)SecurityDescriptor +
(ULONG_PTR)SecurityDescriptor->Group);
+ Sid = (PSID)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Group);
if (Sid->Revision != SID_REVISION)
{
DPRINT1("Invalid Group SID revision\n");
@@ -1186,15 +1150,15 @@
}
/* Check DACL */
- if (SecurityDescriptor->Dacl != NULL)
- {
- if ((ULONG_PTR)SecurityDescriptor->Dacl % sizeof(ULONG))
+ if (SecurityDescriptor->Dacl)
+ {
+ if (SecurityDescriptor->Dacl % sizeof(ULONG))
{
DPRINT1("Invalid DACL alignment\n");
return FALSE;
}
- Acl = (PACL)((ULONG_PTR)SecurityDescriptor +
(ULONG_PTR)SecurityDescriptor->Dacl);
+ Acl = (PACL)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Dacl);
if ((Acl->AclRevision < MIN_ACL_REVISION) &&
(Acl->AclRevision > MAX_ACL_REVISION))
{
@@ -1211,15 +1175,15 @@
}
/* Check SACL */
- if (SecurityDescriptor->Sacl != NULL)
- {
- if ((ULONG_PTR)SecurityDescriptor->Sacl % sizeof(ULONG))
+ if (SecurityDescriptor->Sacl)
+ {
+ if (SecurityDescriptor->Sacl % sizeof(ULONG))
{
DPRINT1("Invalid SACL alignment\n");
return FALSE;
}
- Acl = (PACL)((ULONG_PTR)SecurityDescriptor +
(ULONG_PTR)SecurityDescriptor->Sacl);
+ Acl = (PACL)((ULONG_PTR)SecurityDescriptor + SecurityDescriptor->Sacl);
if ((Acl->AclRevision < MIN_ACL_REVISION) ||
(Acl->AclRevision > MAX_ACL_REVISION))
{
@@ -1254,6 +1218,7 @@
return STATUS_SUCCESS;
}
+
/*
@@ -1288,7 +1253,7 @@
{
PISECURITY_DESCRIPTOR ParentDescriptor = _ParentDescriptor;
PISECURITY_DESCRIPTOR ExplicitDescriptor = _ExplicitDescriptor;
- PISECURITY_DESCRIPTOR Descriptor;
+ PISECURITY_DESCRIPTOR_RELATIVE Descriptor;
PTOKEN Token;
ULONG OwnerLength = 0;
ULONG GroupLength = 0;
@@ -1296,7 +1261,7 @@
ULONG SaclLength = 0;
ULONG Length = 0;
ULONG Control = 0;
- ULONG_PTR Current;
+ ULONG Current;
PSID Owner = NULL;
PSID Group = NULL;
PACL Dacl = NULL;
@@ -1317,17 +1282,13 @@
}
/* Inherit the Owner SID */
- if (ExplicitDescriptor != NULL && ExplicitDescriptor->Owner != NULL)
+ if (ExplicitDescriptor != NULL)
{
DPRINT("Use explicit owner sid!\n");
- Owner = ExplicitDescriptor->Owner;
-
- if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
- {
- Owner = (PSID)(((ULONG_PTR)Owner) + (ULONG_PTR)ExplicitDescriptor);
- }
- }
- else
+ Owner = SepGetOwnerFromDescriptor(ExplicitDescriptor);
+ }
+
+ if (!Owner)
{
if (Token != NULL)
{
@@ -1346,16 +1307,12 @@
OwnerLength = ROUND_UP(RtlLengthSid(Owner), 4);
/* Inherit the Group SID */
- if (ExplicitDescriptor != NULL && ExplicitDescriptor->Group != NULL)
- {
- DPRINT("Use explicit group sid!\n");
- Group = ExplicitDescriptor->Group;
- if (ExplicitDescriptor->Control & SE_SELF_RELATIVE)
- {
- Group = (PSID)(((ULONG_PTR)Group) + (ULONG_PTR)ExplicitDescriptor);
- }
- }
- else
+ if (ExplicitDescriptor != NULL)
+ {
+ Group = SepGetGroupFromDescriptor(ExplicitDescriptor);
+ }
+
+ if (!Group)
{
if (Token != NULL)
{
@@ -1368,7 +1325,7 @@
Group = SeLocalSystemSid;
}
- Control |= SE_OWNER_DEFAULTED;
+ Control |= SE_GROUP_DEFAULTED;
}
GroupLength = ROUND_UP(RtlLengthSid(Group), 4);
@@ -1379,12 +1336,7 @@
!(ExplicitDescriptor->Control & SE_DACL_DEFAULTED))
{
DPRINT("Use explicit DACL!\n");
- Dacl = ExplicitDescriptor->Dacl;
- if (Dacl != NULL && (ExplicitDescriptor->Control &
SE_SELF_RELATIVE))
- {
- Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ExplicitDescriptor);
- }
-
+ Dacl = SepGetDaclFromDescriptor(ExplicitDescriptor);
Control |= SE_DACL_PRESENT;
}
else if (ParentDescriptor != NULL &&
@@ -1392,12 +1344,7 @@
{
DPRINT("Use parent DACL!\n");
/* FIXME: Inherit */
- Dacl = ParentDescriptor->Dacl;
- if (Dacl != NULL && (ParentDescriptor->Control &
SE_SELF_RELATIVE))
- {
- Dacl = (PACL)(((ULONG_PTR)Dacl) + (ULONG_PTR)ParentDescriptor);
- }
-
+ Dacl = SepGetDaclFromDescriptor(ParentDescriptor);
Control |= (SE_DACL_PRESENT | SE_DACL_DEFAULTED);
}
else if (Token != NULL && Token->DefaultDacl != NULL)
@@ -1422,12 +1369,7 @@
!(ExplicitDescriptor->Control & SE_SACL_DEFAULTED))
{
DPRINT("Use explicit SACL!\n");
- Sacl = ExplicitDescriptor->Sacl;
- if (Sacl != NULL && (ExplicitDescriptor->Control &
SE_SELF_RELATIVE))
- {
- Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ExplicitDescriptor);
- }
-
+ Sacl = SepGetSaclFromDescriptor(ExplicitDescriptor);
Control |= SE_SACL_PRESENT;
}
else if (ParentDescriptor != NULL &&
@@ -1435,20 +1377,15 @@
{
DPRINT("Use parent SACL!\n");
/* FIXME: Inherit */
- Sacl = ParentDescriptor->Sacl;
- if (Sacl != NULL && (ParentDescriptor->Control &
SE_SELF_RELATIVE))
- {
- Sacl = (PACL)(((ULONG_PTR)Sacl) + (ULONG_PTR)ParentDescriptor);
- }
-
+ Sacl = SepGetSaclFromDescriptor(ParentDescriptor);
Control |= (SE_SACL_PRESENT | SE_SACL_DEFAULTED);
}
SaclLength = (Sacl != NULL) ? ROUND_UP(Sacl->AclSize, 4) : 0;
/* Allocate and initialize the new security descriptor */
- Length = sizeof(SECURITY_DESCRIPTOR) +
- OwnerLength + GroupLength + DaclLength + SaclLength;
+ Length = sizeof(SECURITY_DESCRIPTOR_RELATIVE) +
+ OwnerLength + GroupLength + DaclLength + SaclLength;
DPRINT("L: sizeof(SECURITY_DESCRIPTOR) %d OwnerLength %d GroupLength %d
DaclLength %d SaclLength %d\n",
sizeof(SECURITY_DESCRIPTOR),
@@ -1457,9 +1394,7 @@
DaclLength,
SaclLength);
- Descriptor = ExAllocatePoolWithTag(PagedPool,
- Length,
- TAG_SD);
+ Descriptor = ExAllocatePoolWithTag(PagedPool, Length, TAG_SD);
if (Descriptor == NULL)
{
DPRINT1("ExAlloctePool() failed\n");
@@ -1467,38 +1402,31 @@
return STATUS_INSUFFICIENT_RESOURCES;
}
- RtlZeroMemory( Descriptor, Length );
- RtlCreateSecurityDescriptor(Descriptor,
- SECURITY_DESCRIPTOR_REVISION);
+ RtlZeroMemory(Descriptor, Length);
+ RtlCreateSecurityDescriptor(Descriptor, SECURITY_DESCRIPTOR_REVISION);
Descriptor->Control = (USHORT)Control | SE_SELF_RELATIVE;
- Current = (ULONG_PTR)Descriptor + sizeof(SECURITY_DESCRIPTOR);
+ Current = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
if (SaclLength != 0)
{
- RtlCopyMemory((PVOID)Current,
- Sacl,
- SaclLength);
- Descriptor->Sacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
+ RtlCopyMemory((PUCHAR)Descriptor + Current, Sacl, SaclLength);
+ Descriptor->Sacl = Current;
Current += SaclLength;
}
if (DaclLength != 0)
{
- RtlCopyMemory((PVOID)Current,
- Dacl,
- DaclLength);
- Descriptor->Dacl = (PACL)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
+ RtlCopyMemory((PUCHAR)Descriptor + Current, Dacl, DaclLength);
+ Descriptor->Dacl = Current;
Current += DaclLength;
}
if (OwnerLength != 0)
{
- RtlCopyMemory((PVOID)Current,
- Owner,
- OwnerLength);
- Descriptor->Owner = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
+ RtlCopyMemory((PUCHAR)Descriptor + Current, Owner, OwnerLength);
+ Descriptor->Owner = Current;
Current += OwnerLength;
DPRINT("Owner of %x at %x\n", Descriptor, Descriptor->Owner);
}
@@ -1509,10 +1437,8 @@
if (GroupLength != 0)
{
- memmove((PVOID)Current,
- Group,
- GroupLength);
- Descriptor->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)Descriptor);
+ RtlCopyMemory((PUCHAR)Descriptor + Current, Group, GroupLength);
+ Descriptor->Group = Current;
}
/* Unlock subject context */