Author: fireball Date: Tue Apr 1 16:09:28 2008 New Revision: 32814
URL: http://svn.reactos.org/svn/reactos?rev=32814&view=rev Log: - Rewrite the SD Cache functions to use the Windows 2003 structures (thanks to Alex for providing them). - Use pushlocks instead of the fast mutex that was previously used. - Improve the performance of some paths by reducing lock acquisition time, and using atomic operations instead when possible. - Implement the exported Ob APIs which were added in Windows XP to access the Sd cache (ObReference/DereferenceSecurityDescriptor and ObLogSecurityDescriptor). These are used by file systems (such as NPFS) on Windows XP and higher.
Added: trunk/reactos/ntoskrnl/ob/obsdcach.c - copied, changed from r32796, trunk/reactos/ntoskrnl/ob/sdcache.c Removed: trunk/reactos/ntoskrnl/ob/sdcache.c Modified: trunk/reactos/ntoskrnl/include/internal/ob.h trunk/reactos/ntoskrnl/include/internal/ob_x.h trunk/reactos/ntoskrnl/ob/obsecure.c
Modified: trunk/reactos/ntoskrnl/include/internal/ob.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/o... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/ob.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/include/internal/ob.h [iso-8859-1] Tue Apr 1 16:09:28 2008 @@ -83,6 +83,18 @@ ((POBJECT_HEADER)((ULONG_PTR)x->Object & ~OBJ_HANDLE_ATTRIBUTES))
// +// Recovers the security descriptor from a cached security descriptor header +// +#define ObpGetHeaderForSd(x) \ + CONTAINING_RECORD((x), SECURITY_DESCRIPTOR_HEADER, SecurityDescriptor) + +// +// Recovers the security descriptor from a cached security descriptor list entry +// +#define ObpGetHeaderForEntry(x) \ + CONTAINING_RECORD((x), SECURITY_DESCRIPTOR_HEADER, Link) + +// // Context Structures for Ex*Handle Callbacks // typedef struct _OBP_SET_HANDLE_ATTRIBUTES_CONTEXT @@ -90,17 +102,39 @@ KPROCESSOR_MODE PreviousMode; OBJECT_HANDLE_ATTRIBUTE_INFORMATION Information; } OBP_SET_HANDLE_ATTRIBUTES_CONTEXT, *POBP_SET_HANDLE_ATTRIBUTES_CONTEXT; + typedef struct _OBP_CLOSE_HANDLE_CONTEXT { PHANDLE_TABLE HandleTable; KPROCESSOR_MODE AccessMode; } OBP_CLOSE_HANDLE_CONTEXT, *POBP_CLOSE_HANDLE_CONTEXT; + typedef struct _OBP_FIND_HANDLE_DATA { POBJECT_HEADER ObjectHeader; POBJECT_TYPE ObjectType; POBJECT_HANDLE_INFORMATION HandleInformation; } OBP_FIND_HANDLE_DATA, *POBP_FIND_HANDLE_DATA; + +// +// Cached Security Descriptor Header +// +typedef struct _SECURITY_DESCRIPTOR_HEADER +{ + LIST_ENTRY Link; + ULONG RefCount; + ULONG FullHash; + QUAD SecurityDescriptor; +} SECURITY_DESCRIPTOR_HEADER, *PSECURITY_DESCRIPTOR_HEADER; + +// +// Cached Security Descriptor List +// +typedef struct _OB_SD_CACHE_LIST +{ + EX_PUSH_LOCK PushLock; + LIST_ENTRY Head; +} OB_SD_CACHE_LIST, *POB_SD_CACHE_LIST;
// // Structure for quick-compare of a DOS Device path @@ -388,23 +422,10 @@ VOID );
-NTSTATUS -NTAPI -ObpAddSecurityDescriptor( - IN PSECURITY_DESCRIPTOR SourceSD, - OUT PSECURITY_DESCRIPTOR *DestinationSD -); - PSECURITY_DESCRIPTOR NTAPI -ObpReferenceCachedSecurityDescriptor( - IN PSECURITY_DESCRIPTOR SecurityDescriptor -); - -VOID -NTAPI -ObpDereferenceCachedSecurityDescriptor( - IN PSECURITY_DESCRIPTOR SecurityDescriptor +ObpReferenceSecurityDescriptor( + IN POBJECT_HEADER ObjectHeader );
//
Modified: trunk/reactos/ntoskrnl/include/internal/ob_x.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/o... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/ob_x.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/include/internal/ob_x.h [iso-8859-1] Tue Apr 1 16:09:28 2008 @@ -29,13 +29,13 @@ { ULONG Slot; POBJECT_TYPE ObjectType = ObjectHeader->Type; - + /* Sanity check */ ASSERT(KeGetCurrentIrql() <= APC_LEVEL); - + /* Pick a slot */ Slot = ObpSelectObjectLockSlot(ObjectHeader); - + /* Enter a critical region and acquire the resource */ KeEnterCriticalRegion(); ExAcquireResourceExclusiveLite(&ObjectType->ObjectLocks[Slot], TRUE); @@ -47,13 +47,13 @@ { ULONG Slot; POBJECT_TYPE ObjectType = ObjectHeader->Type; - + /* Sanity check */ ASSERT(KeGetCurrentIrql() <= APC_LEVEL); - + /* Pick a slot */ Slot = ObpSelectObjectLockSlot(ObjectHeader); - + /* Enter a critical region and acquire the resource */ KeEnterCriticalRegion(); ExAcquireResourceSharedLite(&ObjectType->ObjectLocks[Slot], TRUE); @@ -65,14 +65,14 @@ { ULONG Slot; POBJECT_TYPE ObjectType = ObjectHeader->Type; - + /* Pick a slot */ Slot = ObpSelectObjectLockSlot(ObjectHeader); - - /* Enter a critical region and acquire the resource */ + + /* Release the resource and leave a critical region */ ExReleaseResourceLite(&ObjectType->ObjectLocks[Slot]); KeLeaveCriticalRegion(); - + /* Sanity check */ ASSERT(KeGetCurrentIrql() <= APC_LEVEL); }
Copied: trunk/reactos/ntoskrnl/ob/obsdcach.c (from r32796, trunk/reactos/ntoskrnl/ob/sdcache.c) URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/obsdcach.c?p2=t... ============================================================================== --- trunk/reactos/ntoskrnl/ob/sdcache.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ob/obsdcach.c [iso-8859-1] Tue Apr 1 16:09:28 2008 @@ -7,344 +7,330 @@ * PROGRAMMERS: David Welch (welch@cwcom.net) */
-/* INCLUDES *****************************************************************/ +/* INCLUDES *******************************************************************/
#include <ntoskrnl.h> #define NDEBUG -#include <internal/debug.h> - - -/* TYPES ********************************************************************/ - -typedef struct _SD_CACHE_ENTRY -{ - LIST_ENTRY ListEntry; - ULONG HashValue; - ULONG Index; - ULONG RefCount; -} SD_CACHE_ENTRY, *PSD_CACHE_ENTRY; - - -/* GLOBALS ******************************************************************/ +#include <debug.h> + +/* GLOBALS ********************************************************************/
#define SD_CACHE_ENTRIES 0x100 - -LIST_ENTRY ObpSdCache[SD_CACHE_ENTRIES]; -FAST_MUTEX ObpSdCacheMutex; - -/* FUNCTIONS ****************************************************************/ +OB_SD_CACHE_LIST ObsSecurityDescriptorCache[SD_CACHE_ENTRIES]; + +ULONGLONG Cycles; +ULONG TimeDelta; + +#define ObpSdCacheBeginPerfCount() \ + Cycles = __rdtsc(); + +#define ObpSdCacheEndPerfCount() \ + TimeDelta += __rdtsc() - Cycles; + + +/* PRIVATE FUNCTIONS **********************************************************/ + +VOID +FORCEINLINE +ObpSdAcquireLock(IN POB_SD_CACHE_LIST CacheEntry) +{ + /* Acquire the lock */ + KeEnterCriticalRegion(); + ExAcquirePushLockExclusive(&CacheEntry->PushLock); +} + +VOID +FORCEINLINE +ObpSdReleaseLock(IN POB_SD_CACHE_LIST CacheEntry) +{ + /* Release the lock */ + ExReleasePushLockExclusive(&CacheEntry->PushLock); + KeLeaveCriticalRegion(); +} + +VOID +FORCEINLINE +ObpSdAcquireLockShared(IN POB_SD_CACHE_LIST CacheEntry) +{ + /* Acquire the lock */ + KeEnterCriticalRegion(); + ExAcquirePushLockShared(&CacheEntry->PushLock); +} + +VOID +FORCEINLINE +ObpSdReleaseLockShared(IN POB_SD_CACHE_LIST CacheEntry) +{ + /* Release the lock */ + ExReleasePushLock(&CacheEntry->PushLock); + KeLeaveCriticalRegion(); +}
NTSTATUS NTAPI ObpInitSdCache(VOID) { - ULONG i; - - for (i = 0; i < (sizeof(ObpSdCache) / sizeof(ObpSdCache[0])); i++) - { - InitializeListHead(&ObpSdCache[i]); - } - - ExInitializeFastMutex(&ObpSdCacheMutex); - - return STATUS_SUCCESS; -} - - -static __inline VOID -ObpSdCacheLock(VOID) -{ - /* can't acquire a fast mutex in the early boot process... */ - if(KeGetCurrentThread() != NULL) - { - ExAcquireFastMutex(&ObpSdCacheMutex); - } -} - - -static __inline VOID -ObpSdCacheUnlock(VOID) -{ - /* can't acquire a fast mutex in the early boot process... */ - if(KeGetCurrentThread() != NULL) - { - ExReleaseFastMutex(&ObpSdCacheMutex); - } -} - - -static ULONG -ObpHash(PVOID Buffer, - ULONG Length) -{ - PUCHAR Ptr; - ULONG Value; - ULONG i; - - Ptr = (PUCHAR)Buffer; - Value = 0; - for (i = 0; i < Length; i++) - { - Value += *Ptr; - Ptr++; - } - - return Value; -} - - -static ULONG -ObpHashSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor) -{ - ULONG Value; - BOOLEAN Defaulted; - BOOLEAN DaclPresent; - BOOLEAN SaclPresent; - PSID Owner = NULL; - PSID Group = NULL; - PACL Dacl = NULL; - PACL Sacl = NULL; - - RtlGetOwnerSecurityDescriptor(SecurityDescriptor, - &Owner, - &Defaulted); - - RtlGetGroupSecurityDescriptor(SecurityDescriptor, - &Group, - &Defaulted); - - RtlGetDaclSecurityDescriptor(SecurityDescriptor, - &DaclPresent, - &Dacl, - &Defaulted); - - RtlGetSaclSecurityDescriptor(SecurityDescriptor, - &SaclPresent, - &Sacl, - &Defaulted); - - Value = 0; - if (Owner != NULL) - { - Value += ObpHash(Owner, RtlLengthSid(Owner)); - } - - if (Group != NULL) - { - Value += ObpHash(Group, RtlLengthSid(Group)); - } - - if (DaclPresent == TRUE && Dacl != NULL) - { - Value += ObpHash(Dacl, Dacl->AclSize); - } - - if (SaclPresent == TRUE && Sacl != NULL) - { - Value += ObpHash(Sacl, Sacl->AclSize); - } - - return Value; -} - - -static PSD_CACHE_ENTRY + ULONG i; + + /* Loop each cache entry */ + for (i = 0; i < SD_CACHE_ENTRIES; i++) + { + /* Initialize the lock and the list */ + InitializeListHead(&ObsSecurityDescriptorCache[i].Head); + ExInitializePushLock((PULONG_PTR)&ObsSecurityDescriptorCache[i].PushLock); + } + + /* Return success */ + return STATUS_SUCCESS; +} + +ULONG +NTAPI +ObpHash(IN PVOID Buffer, + IN ULONG Length) +{ + PULONG p, pp; + PUCHAR pb, ppb; + ULONG Hash = 0; + + /* Setup aligned and byte buffers */ + p = Buffer; + ppb = (PUCHAR)((ULONG_PTR)Buffer + Length); + pp = (PULONG)ALIGN_DOWN(p + Length, ULONG); + + /* Loop aligned data */ + while (p < pp) + { + /* XOR-rotate */ + Hash ^= *p++; + Hash = _rotl(Hash, 3); + } + + /* Loop non-aligned data */ + pb = (PUCHAR)p; + while (pb < ppb) + { + /* XOR-rotate */ + Hash ^= *pb++; + Hash = _rotl(Hash, 3); + } + + /* Return the hash */ + return Hash; +} + +ULONG +NTAPI +ObpHashSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN ULONG Length) +{ + /* Just hash the entire SD */ + return ObpHash(SecurityDescriptor, Length); +} + +PSECURITY_DESCRIPTOR_HEADER +NTAPI ObpCreateCacheEntry(IN PSECURITY_DESCRIPTOR SecurityDescriptor, - IN ULONG HashValue, - IN ULONG Index, - OUT PSECURITY_DESCRIPTOR *NewSD) -{ - PSECURITY_DESCRIPTOR Sd; - PSD_CACHE_ENTRY CacheEntry; - ULONG Length; - - DPRINT("ObpCreateCacheEntry() called\n"); - - Length = RtlLengthSecurityDescriptor(SecurityDescriptor); - - CacheEntry = ExAllocatePool(NonPagedPool, - sizeof(SD_CACHE_ENTRY) + Length); - if (CacheEntry == NULL) - { - DPRINT1("ExAllocatePool() failed\n"); - return NULL; - } - - CacheEntry->HashValue = HashValue; - CacheEntry->Index = Index; - CacheEntry->RefCount = 1; - - Sd = (PSECURITY_DESCRIPTOR)(CacheEntry + 1); - RtlCopyMemory(Sd, - SecurityDescriptor, - Length); - - *NewSD = Sd; - - DPRINT("ObpCreateCacheEntry() done\n"); - - return CacheEntry; -} - - -static BOOLEAN + IN ULONG Length, + IN ULONG FullHash, + IN ULONG RefCount) +{ + ULONG CacheSize; + PSECURITY_DESCRIPTOR_HEADER SdHeader; + ASSERT(Length == RtlLengthSecurityDescriptor(SecurityDescriptor)); + + /* Calculate the memory we'll need to allocate and allocate it */ + CacheSize = Length + (sizeof(SECURITY_DESCRIPTOR_HEADER) - sizeof(QUAD)); + SdHeader = ExAllocatePoolWithTag(PagedPool, CacheSize, TAG('O', 'b', 'S', 'c')); + if (!SdHeader) return NULL; + + /* Setup the header */ + SdHeader->RefCount = RefCount; + SdHeader->FullHash = FullHash; + + /* Copy the descriptor */ + RtlCopyMemory(&SdHeader->SecurityDescriptor, SecurityDescriptor, Length); + + /* Return it */ + return SdHeader; +} + +BOOLEAN +NTAPI ObpCompareSecurityDescriptors(IN PSECURITY_DESCRIPTOR Sd1, - IN PSECURITY_DESCRIPTOR Sd2) -{ - ULONG Length1; - ULONG Length2; - - Length1 = RtlLengthSecurityDescriptor(Sd1); - Length2 = RtlLengthSecurityDescriptor(Sd2); - if (Length1 != Length2) - return FALSE; - - if (RtlCompareMemory(Sd1, Sd2, Length1) != Length1) - return FALSE; - - return TRUE; -} - - -NTSTATUS -NTAPI -ObpAddSecurityDescriptor(IN PSECURITY_DESCRIPTOR SourceSD, - OUT PSECURITY_DESCRIPTOR *DestinationSD) -{ - PSECURITY_DESCRIPTOR Sd; - PLIST_ENTRY CurrentEntry; - PSD_CACHE_ENTRY CacheEntry; - ULONG HashValue; - ULONG Index; - NTSTATUS Status; - - DPRINT("ObpAddSecurityDescriptor() called\n"); - - HashValue = ObpHashSecurityDescriptor(SourceSD); - Index = HashValue & 0xFF; - - ObpSdCacheLock(); - - if (!IsListEmpty(&ObpSdCache[Index])) - { - CurrentEntry = ObpSdCache[Index].Flink; - while (CurrentEntry != &ObpSdCache[Index]) - { - CacheEntry = CONTAINING_RECORD(CurrentEntry, - SD_CACHE_ENTRY, - ListEntry); - Sd = (PSECURITY_DESCRIPTOR)(CacheEntry + 1); - - if (CacheEntry->HashValue == HashValue && - ObpCompareSecurityDescriptors(SourceSD, Sd)) - { - CacheEntry->RefCount++; - DPRINT("RefCount %lu\n", CacheEntry->RefCount); - *DestinationSD = Sd; - - ObpSdCacheUnlock(); - - DPRINT("ObpAddSecurityDescriptor() done\n"); - - return STATUS_SUCCESS; - } - - CurrentEntry = CurrentEntry->Flink; - } - } - - CacheEntry = ObpCreateCacheEntry(SourceSD, - HashValue, - Index, - DestinationSD); - if (CacheEntry == NULL) - { - DPRINT1("ObpCreateCacheEntry() failed\n"); - Status = STATUS_INSUFFICIENT_RESOURCES; - } - else - { - DPRINT("RefCount 1\n"); - InsertTailList(&ObpSdCache[Index], &CacheEntry->ListEntry); - Status = STATUS_SUCCESS; - } - - ObpSdCacheUnlock(); - - DPRINT("ObpAddSecurityDescriptor() done\n"); - - return Status; -} - - -NTSTATUS -NTAPI -ObpRemoveSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor) -{ - PSD_CACHE_ENTRY CacheEntry; - - DPRINT("ObpRemoveSecurityDescriptor() called\n"); - - ObpSdCacheLock(); - - CacheEntry = (PSD_CACHE_ENTRY)((ULONG_PTR)SecurityDescriptor - sizeof(SD_CACHE_ENTRY)); - - CacheEntry->RefCount--; - DPRINT("RefCount %lu\n", CacheEntry->RefCount); - if (CacheEntry->RefCount == 0) - { - DPRINT("Remove cache entry\n"); - RemoveEntryList(&CacheEntry->ListEntry); - ExFreePool(CacheEntry); - } - - ObpSdCacheUnlock(); - - DPRINT("ObpRemoveSecurityDescriptor() done\n"); - - return STATUS_SUCCESS; + IN ULONG Length1, + IN PSECURITY_DESCRIPTOR Sd2) +{ + ULONG Length2; + ASSERT(Length1 == RtlLengthSecurityDescriptor(Sd1)); + + /* Get the length of the second SD */ + Length2 = RtlLengthSecurityDescriptor(Sd2); + + /* Compare lengths */ + if (Length1 != Length2) return FALSE; + + /* Compare contents */ + return RtlEqualMemory(Sd1, Sd2, Length1); +} + +PVOID +NTAPI +ObpDestroySecurityDescriptorHeader(IN PSECURITY_DESCRIPTOR_HEADER SdHeader) +{ + ASSERT(SdHeader->RefCount == 0); + + /* Just unlink the SD and return it back to the caller */ + RemoveEntryList(&SdHeader->Link); + return SdHeader; }
PSECURITY_DESCRIPTOR NTAPI -ObpReferenceCachedSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor) -{ - PSD_CACHE_ENTRY CacheEntry; - - /* Lock the cache */ - ObpSdCacheLock(); - - /* Make sure we got a descriptor */ - if (SecurityDescriptor) - { - /* Get the entry */ - CacheEntry = (PSD_CACHE_ENTRY)((ULONG_PTR)SecurityDescriptor - - sizeof(SD_CACHE_ENTRY)); - - /* Reference it */ - CacheEntry->RefCount++; - DPRINT("RefCount %lu\n", CacheEntry->RefCount); - } - - /* Unlock the cache and return the descriptor */ - ObpSdCacheUnlock(); +ObpReferenceSecurityDescriptor(IN POBJECT_HEADER ObjectHeader) +{ + PSECURITY_DESCRIPTOR SecurityDescriptor; + PSECURITY_DESCRIPTOR_HEADER SdHeader; + ObpSdCacheBeginPerfCount(); + + /* Get the SD */ + SecurityDescriptor = ObjectHeader->SecurityDescriptor; + if (!SecurityDescriptor) + { + /* No SD, nothing to do */ + ObpSdCacheEndPerfCount(); + return NULL; + } + + /* Lock the object */ + ObpAcquireObjectLockShared(ObjectHeader); + + /* Get the object header */ + SdHeader = ObpGetHeaderForSd(SecurityDescriptor); + + /* Do the reference */ + InterlockedIncrement((PLONG)&SdHeader->RefCount); + + /* Release the lock and return */ + ObpReleaseObjectLock(ObjectHeader); + ObpSdCacheEndPerfCount(); return SecurityDescriptor; }
-VOID -NTAPI -ObpDereferenceCachedSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor) -{ - DPRINT("ObpDereferenceCachedSecurityDescriptor() called\n"); - - ObpRemoveSecurityDescriptor(SecurityDescriptor); - - DPRINT("ObpDereferenceCachedSecurityDescriptor() done\n"); +/* PUBLIC FUNCTIONS ***********************************************************/ + +/*++ + * @name ObReferenceSecurityDescriptor + * @implemented NT5.2 + * + * The ObReferenceSecurityDescriptor routine <FILLMEIN> + * + * @param SecurityDescriptor + * <FILLMEIN> + * + * @param Count + * <FILLMEIN> + * + * @return STATUS_SUCCESS or appropriate error value. + * + * @remarks None. + * + *--*/ +VOID +NTAPI +ObReferenceSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN ULONG Count) +{ + PSECURITY_DESCRIPTOR_HEADER SdHeader; + ObpSdCacheBeginPerfCount(); + + /* Get the header */ + SdHeader = ObpGetHeaderForSd(SecurityDescriptor); + + /* Do the references */ + InterlockedExchangeAdd((PLONG)&SdHeader->RefCount, Count); + ObpSdCacheEndPerfCount(); +} + +/*++ + * @name ObDereferenceSecurityDescriptor + * @implemented NT5.2 + * + * The ObDereferenceSecurityDescriptor routine <FILLMEIN> + * + * @param SecurityDescriptor + * <FILLMEIN> + * + * @param Count + * <FILLMEIN> + * + * @return STATUS_SUCCESS or appropriate error value. + * + * @remarks None. + * + *--*/ +VOID +NTAPI +ObDereferenceSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, + IN ULONG Count) +{ + PSECURITY_DESCRIPTOR_HEADER SdHeader; + LONG OldValue, NewValue; + ULONG Index; + POB_SD_CACHE_LIST CacheEntry; + ObpSdCacheBeginPerfCount(); + + /* Get the header */ + SdHeader = ObpGetHeaderForSd(SecurityDescriptor); + + /* Get the current reference count */ + OldValue = SdHeader->RefCount; + + /* Check if the caller is destroying this SD -- we need the lock for that */ + while (OldValue != Count) + { + /* He isn't, we can just try to derefeference atomically */ + NewValue = InterlockedCompareExchange((PLONG)&SdHeader->RefCount, + OldValue - Count, + OldValue); + if (NewValue == OldValue) ObpSdCacheEndPerfCount(); return; + + /* Try again */ + OldValue = NewValue; + } + + /* At this point, we need the lock, so choose an entry */ + Index = SdHeader->FullHash % SD_CACHE_ENTRIES; + CacheEntry = &ObsSecurityDescriptorCache[Index]; + + /* Acquire the lock for it */ + ObpSdAcquireLock(CacheEntry); + ASSERT(SdHeader->RefCount != 0); + + /* Now do the dereference */ + if (InterlockedExchangeAdd((PLONG)&SdHeader->RefCount, -(LONG)Count) == Count) + { + /* We're down to zero -- destroy the header */ + SdHeader = ObpDestroySecurityDescriptorHeader(SdHeader); + + /* Release the lock */ + ObpSdReleaseLock(CacheEntry); + + /* Free the header */ + ExFreePool(SdHeader); + } + else + { + /* Just release the lock */ + ObpSdReleaseLock(CacheEntry); + } + + ObpSdCacheEndPerfCount(); }
/*++ * @name ObLogSecurityDescriptor -* @unimplemented NT5.2 +* @implemented NT5.2 * * The ObLogSecurityDescriptor routine <FILLMEIN> * @@ -368,42 +354,107 @@ OUT PSECURITY_DESCRIPTOR *OutputSecurityDescriptor, IN ULONG RefBias) { - /* HACK: Return the same descriptor back */ - PISECURITY_DESCRIPTOR SdCopy; - ULONG Length; - DPRINT("ObLogSecurityDescriptor is not implemented!\n", - InputSecurityDescriptor); - + PSECURITY_DESCRIPTOR_HEADER SdHeader = NULL, NewHeader = NULL; + ULONG Length, Hash, Index; + POB_SD_CACHE_LIST CacheEntry; + BOOLEAN Result; + PLIST_ENTRY NextEntry; + ObpSdCacheBeginPerfCount(); + + /* Get the length */ Length = RtlLengthSecurityDescriptor(InputSecurityDescriptor); - SdCopy = ExAllocatePool(PagedPool, Length); - RtlCopyMemory(SdCopy, InputSecurityDescriptor, Length); - *OutputSecurityDescriptor = SdCopy; + + /* Get the hash */ + Hash = ObpHashSecurityDescriptor(InputSecurityDescriptor, Length); + + /* Now select the appropriate cache entry */ + Index = Hash % SD_CACHE_ENTRIES; + CacheEntry = &ObsSecurityDescriptorCache[Index]; + + /* Lock it shared */ + ObpSdAcquireLockShared(CacheEntry); + + /* Start our search */ + while (TRUE) + { + /* Reset result found */ + Result = FALSE; + + /* Loop the hash list */ + NextEntry = CacheEntry->Head.Flink; + while (NextEntry != &CacheEntry->Head) + { + /* Get the header */ + SdHeader = ObpGetHeaderForEntry(NextEntry); + + /* Our hashes are ordered, so quickly check if we should stop now */ + if (SdHeader->FullHash > Hash) break; + + /* We survived the quick hash check, now check for equalness */ + if (SdHeader->FullHash == Hash) + { + /* Hashes match, now compare descriptors */ + Result = ObpCompareSecurityDescriptors(InputSecurityDescriptor, + Length, + &SdHeader->SecurityDescriptor); + if (Result) break; + } + + /* Go to the next entry */ + NextEntry = NextEntry->Flink; + } + + /* Check if we found anything */ + if (Result) + { + /* Increment its reference count */ + InterlockedExchangeAdd((PLONG)&SdHeader->RefCount, RefBias); + + /* Release the lock */ + ObpSdReleaseLockShared(CacheEntry); + + /* Return the descriptor */ + *OutputSecurityDescriptor = &SdHeader->SecurityDescriptor; + + /* Free anything that we may have had to create */ + if (NewHeader) ExFreePool(NewHeader); + ObpSdCacheEndPerfCount(); + return STATUS_SUCCESS; + } + + /* Check if we got here, and didn't create a descriptor yet */ + if (!NewHeader) + { + /* Release the lock */ + ObpSdReleaseLockShared(CacheEntry); + + /* This should be our first time in the loop, create it */ + NewHeader = ObpCreateCacheEntry(InputSecurityDescriptor, + Length, + Hash, + RefBias); + if (!NewHeader) return STATUS_INSUFFICIENT_RESOURCES; + + /* Now acquire the exclusive lock and we should hit the right path */ + ObpSdAcquireLock(CacheEntry); + } + else + { + /* We have inserted the SD, we're fine now */ + break; + } + } + + /* Okay, now let's do the insert, we should have the exclusive lock */ + InsertTailList(NextEntry, &NewHeader->Link); + + /* Release the lock */ + ObpSdReleaseLock(CacheEntry); + + /* Return the SD*/ + *OutputSecurityDescriptor = &NewHeader->SecurityDescriptor; + ObpSdCacheEndPerfCount(); return STATUS_SUCCESS; }
-/*++ -* @name ObDereferenceSecurityDescriptor -* @unimplemented NT5.2 -* -* The ObDereferenceSecurityDescriptor routine <FILLMEIN> -* -* @param SecurityDescriptor -* <FILLMEIN> -* -* @param Count -* <FILLMEIN> -* -* @return STATUS_SUCCESS or appropriate error value. -* -* @remarks None. -* -*--*/ -VOID -NTAPI -ObDereferenceSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, - IN ULONG Count) -{ - DPRINT1("ObDereferenceSecurityDescriptor is not implemented!\n"); -} - /* EOF */
Modified: trunk/reactos/ntoskrnl/ob/obsecure.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/obsecure.c?rev=... ============================================================================== --- trunk/reactos/ntoskrnl/ob/obsecure.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ob/obsecure.c [iso-8859-1] Tue Apr 1 16:09:28 2008 @@ -25,7 +25,7 @@ NTSTATUS Status; PSECURITY_DESCRIPTOR NewSd; PAGED_CODE(); - + /* Get the object header */ ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); if (!SecurityDescriptor) @@ -34,19 +34,19 @@ ObjectHeader->SecurityDescriptor = NULL; return STATUS_SUCCESS; } - + /* Add it to our internal cache */ - Status = ObpAddSecurityDescriptor(SecurityDescriptor, &NewSd); + Status = ObLogSecurityDescriptor(SecurityDescriptor, &NewSd, 1); if (NT_SUCCESS(Status)) { /* Free the old copy */ ExFreePool(SecurityDescriptor); - + /* Set the new pointer */ ASSERT(NewSd); ObjectHeader->SecurityDescriptor = NewSd; } - + /* Return status */ return Status; } @@ -56,11 +56,11 @@ ObDeassignSecurity(IN OUT PSECURITY_DESCRIPTOR *SecurityDescriptor) { /* Dereference it */ - ObpDereferenceCachedSecurityDescriptor(*SecurityDescriptor); - + ObDereferenceSecurityDescriptor(*SecurityDescriptor, 1); + /* Don't free again later */ *SecurityDescriptor = NULL; - + /* All done */ return STATUS_SUCCESS; } @@ -77,13 +77,13 @@ NTSTATUS Status; PSECURITY_DESCRIPTOR ObjectSd; PAGED_CODE(); - + /* Get the object header */ ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); - + /* Get the SD */ - ObjectSd = ObpReferenceCachedSecurityDescriptor(ObjectHeader->SecurityDescriptor); - + ObjectSd = ObpReferenceSecurityDescriptor(ObjectHeader); + /* Query the information */ Status = SeQuerySecurityDescriptorInfo(SecurityInformation, SecurityDescriptor, @@ -91,8 +91,8 @@ &ObjectSd);
/* Check if we have an object SD and dereference it, if so */ - if (ObjectSd) ObpDereferenceCachedSecurityDescriptor(ObjectSd); - + if (ObjectSd) ObDereferenceSecurityDescriptor(ObjectSd, 1); + /* Return status */ return Status; } @@ -110,15 +110,15 @@ POBJECT_HEADER ObjectHeader; PSECURITY_DESCRIPTOR OldDescriptor, NewDescriptor, CachedDescriptor; PAGED_CODE(); - + /* Get the object header */ ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); while (TRUE) { /* Reference the old descriptor */ - OldDescriptor = ObpReferenceCachedSecurityDescriptor(ObjectHeader->SecurityDescriptor); + OldDescriptor = ObpReferenceSecurityDescriptor(ObjectHeader); NewDescriptor = OldDescriptor; - + /* Set the SD information */ Status = SeSetSecurityDescriptorInfo(Object, SecurityInformation, @@ -129,39 +129,39 @@ if (NT_SUCCESS(Status)) { /* Now add this to the cache */ - Status = ObpAddSecurityDescriptor(NewDescriptor, &CachedDescriptor); - + Status = ObLogSecurityDescriptor(NewDescriptor, &CachedDescriptor, 1); + /* Let go of our uncached copy */ ExFreePool(NewDescriptor); - + /* Check for success */ if (NT_SUCCESS(Status)) { /* Dereference the old one */ ASSERT(OldDescriptor == ObjectHeader->SecurityDescriptor); - + /* Now set this as the new descriptor */ ObjectHeader->SecurityDescriptor = CachedDescriptor; - + /* And dereference the old one */ - ObpDereferenceCachedSecurityDescriptor(OldDescriptor); + ObDereferenceSecurityDescriptor(OldDescriptor, 1); break; } else { /* We failed, dereference the old one */ - ObpDereferenceCachedSecurityDescriptor(OldDescriptor); + ObDereferenceSecurityDescriptor(OldDescriptor, 1); break; } } else { /* We failed, dereference the old one */ - if (OldDescriptor) ObpDereferenceCachedSecurityDescriptor(OldDescriptor); + if (OldDescriptor) ObDereferenceSecurityDescriptor(OldDescriptor, 1); break; } } - + /* Return status */ return Status; } @@ -585,8 +585,7 @@ if (Type->TypeInfo.SecurityProcedure == SeDefaultObjectMethod) { /* Reference the descriptor */ - *SecurityDescriptor = - ObpReferenceCachedSecurityDescriptor(Header->SecurityDescriptor); + *SecurityDescriptor = ObpReferenceSecurityDescriptor(Header); return STATUS_SUCCESS; }
@@ -678,7 +677,7 @@ else { /* Otherwise this means we used an internal descriptor */ - ObpDereferenceCachedSecurityDescriptor(SecurityDescriptor); + ObDereferenceSecurityDescriptor(SecurityDescriptor, 1); } }
Removed: trunk/reactos/ntoskrnl/ob/sdcache.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/sdcache.c?rev=3... ============================================================================== --- trunk/reactos/ntoskrnl/ob/sdcache.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ob/sdcache.c (removed) @@ -1,409 +1,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ob/sdcache.c - * PURPOSE: No purpose listed. - * - * PROGRAMMERS: David Welch (welch@cwcom.net) - */ - -/* INCLUDES *****************************************************************/ - -#include <ntoskrnl.h> -#define NDEBUG -#include <internal/debug.h> - - -/* TYPES ********************************************************************/ - -typedef struct _SD_CACHE_ENTRY -{ - LIST_ENTRY ListEntry; - ULONG HashValue; - ULONG Index; - ULONG RefCount; -} SD_CACHE_ENTRY, *PSD_CACHE_ENTRY; - - -/* GLOBALS ******************************************************************/ - -#define SD_CACHE_ENTRIES 0x100 - -LIST_ENTRY ObpSdCache[SD_CACHE_ENTRIES]; -FAST_MUTEX ObpSdCacheMutex; - -/* FUNCTIONS ****************************************************************/ - -NTSTATUS -NTAPI -ObpInitSdCache(VOID) -{ - ULONG i; - - for (i = 0; i < (sizeof(ObpSdCache) / sizeof(ObpSdCache[0])); i++) - { - InitializeListHead(&ObpSdCache[i]); - } - - ExInitializeFastMutex(&ObpSdCacheMutex); - - return STATUS_SUCCESS; -} - - -static __inline VOID -ObpSdCacheLock(VOID) -{ - /* can't acquire a fast mutex in the early boot process... */ - if(KeGetCurrentThread() != NULL) - { - ExAcquireFastMutex(&ObpSdCacheMutex); - } -} - - -static __inline VOID -ObpSdCacheUnlock(VOID) -{ - /* can't acquire a fast mutex in the early boot process... */ - if(KeGetCurrentThread() != NULL) - { - ExReleaseFastMutex(&ObpSdCacheMutex); - } -} - - -static ULONG -ObpHash(PVOID Buffer, - ULONG Length) -{ - PUCHAR Ptr; - ULONG Value; - ULONG i; - - Ptr = (PUCHAR)Buffer; - Value = 0; - for (i = 0; i < Length; i++) - { - Value += *Ptr; - Ptr++; - } - - return Value; -} - - -static ULONG -ObpHashSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor) -{ - ULONG Value; - BOOLEAN Defaulted; - BOOLEAN DaclPresent; - BOOLEAN SaclPresent; - PSID Owner = NULL; - PSID Group = NULL; - PACL Dacl = NULL; - PACL Sacl = NULL; - - RtlGetOwnerSecurityDescriptor(SecurityDescriptor, - &Owner, - &Defaulted); - - RtlGetGroupSecurityDescriptor(SecurityDescriptor, - &Group, - &Defaulted); - - RtlGetDaclSecurityDescriptor(SecurityDescriptor, - &DaclPresent, - &Dacl, - &Defaulted); - - RtlGetSaclSecurityDescriptor(SecurityDescriptor, - &SaclPresent, - &Sacl, - &Defaulted); - - Value = 0; - if (Owner != NULL) - { - Value += ObpHash(Owner, RtlLengthSid(Owner)); - } - - if (Group != NULL) - { - Value += ObpHash(Group, RtlLengthSid(Group)); - } - - if (DaclPresent == TRUE && Dacl != NULL) - { - Value += ObpHash(Dacl, Dacl->AclSize); - } - - if (SaclPresent == TRUE && Sacl != NULL) - { - Value += ObpHash(Sacl, Sacl->AclSize); - } - - return Value; -} - - -static PSD_CACHE_ENTRY -ObpCreateCacheEntry(IN PSECURITY_DESCRIPTOR SecurityDescriptor, - IN ULONG HashValue, - IN ULONG Index, - OUT PSECURITY_DESCRIPTOR *NewSD) -{ - PSECURITY_DESCRIPTOR Sd; - PSD_CACHE_ENTRY CacheEntry; - ULONG Length; - - DPRINT("ObpCreateCacheEntry() called\n"); - - Length = RtlLengthSecurityDescriptor(SecurityDescriptor); - - CacheEntry = ExAllocatePool(NonPagedPool, - sizeof(SD_CACHE_ENTRY) + Length); - if (CacheEntry == NULL) - { - DPRINT1("ExAllocatePool() failed\n"); - return NULL; - } - - CacheEntry->HashValue = HashValue; - CacheEntry->Index = Index; - CacheEntry->RefCount = 1; - - Sd = (PSECURITY_DESCRIPTOR)(CacheEntry + 1); - RtlCopyMemory(Sd, - SecurityDescriptor, - Length); - - *NewSD = Sd; - - DPRINT("ObpCreateCacheEntry() done\n"); - - return CacheEntry; -} - - -static BOOLEAN -ObpCompareSecurityDescriptors(IN PSECURITY_DESCRIPTOR Sd1, - IN PSECURITY_DESCRIPTOR Sd2) -{ - ULONG Length1; - ULONG Length2; - - Length1 = RtlLengthSecurityDescriptor(Sd1); - Length2 = RtlLengthSecurityDescriptor(Sd2); - if (Length1 != Length2) - return FALSE; - - if (RtlCompareMemory(Sd1, Sd2, Length1) != Length1) - return FALSE; - - return TRUE; -} - - -NTSTATUS -NTAPI -ObpAddSecurityDescriptor(IN PSECURITY_DESCRIPTOR SourceSD, - OUT PSECURITY_DESCRIPTOR *DestinationSD) -{ - PSECURITY_DESCRIPTOR Sd; - PLIST_ENTRY CurrentEntry; - PSD_CACHE_ENTRY CacheEntry; - ULONG HashValue; - ULONG Index; - NTSTATUS Status; - - DPRINT("ObpAddSecurityDescriptor() called\n"); - - HashValue = ObpHashSecurityDescriptor(SourceSD); - Index = HashValue & 0xFF; - - ObpSdCacheLock(); - - if (!IsListEmpty(&ObpSdCache[Index])) - { - CurrentEntry = ObpSdCache[Index].Flink; - while (CurrentEntry != &ObpSdCache[Index]) - { - CacheEntry = CONTAINING_RECORD(CurrentEntry, - SD_CACHE_ENTRY, - ListEntry); - Sd = (PSECURITY_DESCRIPTOR)(CacheEntry + 1); - - if (CacheEntry->HashValue == HashValue && - ObpCompareSecurityDescriptors(SourceSD, Sd)) - { - CacheEntry->RefCount++; - DPRINT("RefCount %lu\n", CacheEntry->RefCount); - *DestinationSD = Sd; - - ObpSdCacheUnlock(); - - DPRINT("ObpAddSecurityDescriptor() done\n"); - - return STATUS_SUCCESS; - } - - CurrentEntry = CurrentEntry->Flink; - } - } - - CacheEntry = ObpCreateCacheEntry(SourceSD, - HashValue, - Index, - DestinationSD); - if (CacheEntry == NULL) - { - DPRINT1("ObpCreateCacheEntry() failed\n"); - Status = STATUS_INSUFFICIENT_RESOURCES; - } - else - { - DPRINT("RefCount 1\n"); - InsertTailList(&ObpSdCache[Index], &CacheEntry->ListEntry); - Status = STATUS_SUCCESS; - } - - ObpSdCacheUnlock(); - - DPRINT("ObpAddSecurityDescriptor() done\n"); - - return Status; -} - - -NTSTATUS -NTAPI -ObpRemoveSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor) -{ - PSD_CACHE_ENTRY CacheEntry; - - DPRINT("ObpRemoveSecurityDescriptor() called\n"); - - ObpSdCacheLock(); - - CacheEntry = (PSD_CACHE_ENTRY)((ULONG_PTR)SecurityDescriptor - sizeof(SD_CACHE_ENTRY)); - - CacheEntry->RefCount--; - DPRINT("RefCount %lu\n", CacheEntry->RefCount); - if (CacheEntry->RefCount == 0) - { - DPRINT("Remove cache entry\n"); - RemoveEntryList(&CacheEntry->ListEntry); - ExFreePool(CacheEntry); - } - - ObpSdCacheUnlock(); - - DPRINT("ObpRemoveSecurityDescriptor() done\n"); - - return STATUS_SUCCESS; -} - -PSECURITY_DESCRIPTOR -NTAPI -ObpReferenceCachedSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor) -{ - PSD_CACHE_ENTRY CacheEntry; - - /* Lock the cache */ - ObpSdCacheLock(); - - /* Make sure we got a descriptor */ - if (SecurityDescriptor) - { - /* Get the entry */ - CacheEntry = (PSD_CACHE_ENTRY)((ULONG_PTR)SecurityDescriptor - - sizeof(SD_CACHE_ENTRY)); - - /* Reference it */ - CacheEntry->RefCount++; - DPRINT("RefCount %lu\n", CacheEntry->RefCount); - } - - /* Unlock the cache and return the descriptor */ - ObpSdCacheUnlock(); - return SecurityDescriptor; -} - -VOID -NTAPI -ObpDereferenceCachedSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor) -{ - DPRINT("ObpDereferenceCachedSecurityDescriptor() called\n"); - - ObpRemoveSecurityDescriptor(SecurityDescriptor); - - DPRINT("ObpDereferenceCachedSecurityDescriptor() done\n"); -} - -/*++ -* @name ObLogSecurityDescriptor -* @unimplemented NT5.2 -* -* The ObLogSecurityDescriptor routine <FILLMEIN> -* -* @param InputSecurityDescriptor -* <FILLMEIN> -* -* @param OutputSecurityDescriptor -* <FILLMEIN> -* -* @param RefBias -* <FILLMEIN> -* -* @return STATUS_SUCCESS or appropriate error value. -* -* @remarks None. -* -*--*/ -NTSTATUS -NTAPI -ObLogSecurityDescriptor(IN PSECURITY_DESCRIPTOR InputSecurityDescriptor, - OUT PSECURITY_DESCRIPTOR *OutputSecurityDescriptor, - IN ULONG RefBias) -{ - /* HACK: Return the same descriptor back */ - PISECURITY_DESCRIPTOR SdCopy; - ULONG Length; - DPRINT("ObLogSecurityDescriptor is not implemented!\n", - InputSecurityDescriptor); - - Length = RtlLengthSecurityDescriptor(InputSecurityDescriptor); - SdCopy = ExAllocatePool(PagedPool, Length); - RtlCopyMemory(SdCopy, InputSecurityDescriptor, Length); - *OutputSecurityDescriptor = SdCopy; - return STATUS_SUCCESS; -} - -/*++ -* @name ObDereferenceSecurityDescriptor -* @unimplemented NT5.2 -* -* The ObDereferenceSecurityDescriptor routine <FILLMEIN> -* -* @param SecurityDescriptor -* <FILLMEIN> -* -* @param Count -* <FILLMEIN> -* -* @return STATUS_SUCCESS or appropriate error value. -* -* @remarks None. -* -*--*/ -VOID -NTAPI -ObDereferenceSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, - IN ULONG Count) -{ - DPRINT1("ObDereferenceSecurityDescriptor is not implemented!\n"); -} - -/* EOF */