- Make TOKEN pointer in OBJECT_HEADER a fast reference, just like on Windows.

- Update SD cache code to treat it as such.
- Improves performance by 500% during security checks - noticeable impact during large file or registry transfer operations.

svn path=/trunk/; revision=39876
This commit is contained in:
Aleksey Bragin 2009-03-04 20:58:32 +00:00
parent 78cc4931af
commit d6b8e5ff23
2 changed files with 91 additions and 25 deletions

View file

@ -181,24 +181,51 @@ ObpReferenceSecurityDescriptor(IN POBJECT_HEADER ObjectHeader)
{
PSECURITY_DESCRIPTOR SecurityDescriptor;
PSECURITY_DESCRIPTOR_HEADER SdHeader;
/* Get the SD */
SecurityDescriptor = ObjectHeader->SecurityDescriptor;
if (!SecurityDescriptor)
PEX_FAST_REF FastRef;
EX_FAST_REF OldValue;
ULONG_PTR Count;
/* Acquire a reference to the security descriptor */
FastRef = (PEX_FAST_REF)&ObjectHeader->SecurityDescriptor;
OldValue = ExAcquireFastReference(FastRef);
/* Get the descriptor and reference count */
SecurityDescriptor = ExGetObjectFastReference(OldValue);
Count = ExGetCountFastReference(OldValue);
/* Check if there's no descriptor or if there's still cached references */
if ((Count >= 1) || !(SecurityDescriptor))
{
/* No SD, nothing to do */
return NULL;
/* Check if this is the last reference */
if (Count == 1)
{
/* Add the extra references that we'll take */
SdHeader = ObpGetHeaderForSd(SecurityDescriptor);
InterlockedExchangeAdd((PLONG)&SdHeader->RefCount, MAX_FAST_REFS);
/* Now insert them */
if (!ExInsertFastReference(FastRef, SecurityDescriptor))
{
/* Undo the references since we failed */
InterlockedExchangeAdd((PLONG)&SdHeader->RefCount,
-MAX_FAST_REFS);
}
}
/* Return the SD */
return SecurityDescriptor;
}
/* Lock the object */
ObpAcquireObjectLockShared(ObjectHeader);
/* Get the object header */
SecurityDescriptor = ExGetObjectFastReference(*FastRef);
SdHeader = ObpGetHeaderForSd(SecurityDescriptor);
/* Do the reference */
InterlockedIncrement((PLONG)&SdHeader->RefCount);
/* Release the lock and return */
ObpReleaseObjectLock(ObjectHeader);
return SecurityDescriptor;

View file

@ -24,19 +24,23 @@ ObAssignObjectSecurityDescriptor(IN PVOID Object,
POBJECT_HEADER ObjectHeader;
NTSTATUS Status;
PSECURITY_DESCRIPTOR NewSd;
PEX_FAST_REF FastRef;
PAGED_CODE();
/* Get the object header */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
FastRef = (PEX_FAST_REF)&ObjectHeader->SecurityDescriptor;
if (!SecurityDescriptor)
{
/* Nothing to assign */
ObjectHeader->SecurityDescriptor = NULL;
ExInitializeFastReference(FastRef, NULL);
return STATUS_SUCCESS;
}
/* Add it to our internal cache */
Status = ObLogSecurityDescriptor(SecurityDescriptor, &NewSd, 1);
Status = ObLogSecurityDescriptor(SecurityDescriptor,
&NewSd,
MAX_FAST_REFS + 1);
if (NT_SUCCESS(Status))
{
/* Free the old copy */
@ -44,7 +48,7 @@ ObAssignObjectSecurityDescriptor(IN PVOID Object,
/* Set the new pointer */
ASSERT(NewSd);
ObjectHeader->SecurityDescriptor = NewSd;
ExInitializeFastReference(FastRef, NewSd);
}
/* Return status */
@ -55,11 +59,22 @@ NTSTATUS
NTAPI
ObDeassignSecurity(IN OUT PSECURITY_DESCRIPTOR *SecurityDescriptor)
{
/* Dereference it */
ObDereferenceSecurityDescriptor(*SecurityDescriptor, 1);
EX_FAST_REF FastRef;
ULONG_PTR Count;
PSECURITY_DESCRIPTOR OldSecurityDescriptor;
/* Get the fast reference and capture it */
FastRef = *(PEX_FAST_REF)SecurityDescriptor;
/* Don't free again later */
*SecurityDescriptor = NULL;
/* Get the descriptor and reference count */
OldSecurityDescriptor = ExGetObjectFastReference(FastRef);
Count = ExGetCountFastReference(FastRef);
/* Dereference the descriptor */
ObDereferenceSecurityDescriptor(OldSecurityDescriptor, Count + 1);
/* All done */
return STATUS_SUCCESS;
@ -109,6 +124,9 @@ ObSetSecurityDescriptorInfo(IN PVOID Object,
NTSTATUS Status;
POBJECT_HEADER ObjectHeader;
PSECURITY_DESCRIPTOR OldDescriptor, NewDescriptor, CachedDescriptor;
PEX_FAST_REF FastRef;
EX_FAST_REF OldValue;
ULONG_PTR Count;
PAGED_CODE();
/* Get the object header */
@ -129,7 +147,9 @@ ObSetSecurityDescriptorInfo(IN PVOID Object,
if (NT_SUCCESS(Status))
{
/* Now add this to the cache */
Status = ObLogSecurityDescriptor(NewDescriptor, &CachedDescriptor, 1);
Status = ObLogSecurityDescriptor(NewDescriptor,
&CachedDescriptor,
MAX_FAST_REFS + 1);
/* Let go of our uncached copy */
ExFreePool(NewDescriptor);
@ -137,15 +157,34 @@ ObSetSecurityDescriptorInfo(IN PVOID Object,
/* Check for success */
if (NT_SUCCESS(Status))
{
/* Dereference the old one */
ASSERT(OldDescriptor == ObjectHeader->SecurityDescriptor);
/* Do the swap */
FastRef = (PEX_FAST_REF)OutputSecurityDescriptor;
OldValue = ExCompareSwapFastReference(FastRef,
CachedDescriptor,
OldDescriptor);
/* Get the security descriptor */
SecurityDescriptor = ExGetObjectFastReference(OldValue);
Count = ExGetCountFastReference(OldValue);
/* Make sure the swap worked */
if (SecurityDescriptor == OldDescriptor)
{
/* Flush waiters */
ObpAcquireObjectLock(ObjectHeader);
ObpReleaseObjectLock(ObjectHeader);
/* Now set this as the new descriptor */
ObjectHeader->SecurityDescriptor = CachedDescriptor;
/* And dereference the old one */
ObDereferenceSecurityDescriptor(OldDescriptor, 1);
break;
/* And dereference the old one */
ObDereferenceSecurityDescriptor(OldDescriptor, Count + 2);
break;
}
else
{
/* Someone changed it behind our back -- try again */
ObDereferenceSecurityDescriptor(OldDescriptor, 1);
ObDereferenceSecurityDescriptor(CachedDescriptor,
MAX_FAST_REFS + 1);
}
}
else
{