mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 00:45:24 +00:00
- 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. svn path=/trunk/; revision=32814
This commit is contained in:
parent
1417fd5fa6
commit
007702fce4
5 changed files with 534 additions and 463 deletions
|
@ -82,6 +82,18 @@
|
|||
#define ObpGetHandleObject(x) \
|
||||
((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
|
||||
//
|
||||
|
@ -90,11 +102,13 @@ typedef struct _OBP_SET_HANDLE_ATTRIBUTES_CONTEXT
|
|||
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;
|
||||
|
@ -102,6 +116,26 @@ typedef struct _OBP_FIND_HANDLE_DATA
|
|||
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 @@ ObpInitSdCache(
|
|||
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
|
||||
);
|
||||
|
||||
//
|
||||
|
|
|
@ -69,7 +69,7 @@ ObpReleaseObjectLock(IN POBJECT_HEADER ObjectHeader)
|
|||
/* 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();
|
||||
|
||||
|
|
460
reactos/ntoskrnl/ob/obsdcach.c
Normal file
460
reactos/ntoskrnl/ob/obsdcach.c
Normal file
|
@ -0,0 +1,460 @@
|
|||
/*
|
||||
* 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 <debug.h>
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
#define SD_CACHE_ENTRIES 0x100
|
||||
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;
|
||||
|
||||
/* 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 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 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
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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
|
||||
* @implemented 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)
|
||||
{
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* EOF */
|
|
@ -36,7 +36,7 @@ ObAssignObjectSecurityDescriptor(IN PVOID Object,
|
|||
}
|
||||
|
||||
/* Add it to our internal cache */
|
||||
Status = ObpAddSecurityDescriptor(SecurityDescriptor, &NewSd);
|
||||
Status = ObLogSecurityDescriptor(SecurityDescriptor, &NewSd, 1);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Free the old copy */
|
||||
|
@ -56,7 +56,7 @@ NTAPI
|
|||
ObDeassignSecurity(IN OUT PSECURITY_DESCRIPTOR *SecurityDescriptor)
|
||||
{
|
||||
/* Dereference it */
|
||||
ObpDereferenceCachedSecurityDescriptor(*SecurityDescriptor);
|
||||
ObDereferenceSecurityDescriptor(*SecurityDescriptor, 1);
|
||||
|
||||
/* Don't free again later */
|
||||
*SecurityDescriptor = NULL;
|
||||
|
@ -82,7 +82,7 @@ ObQuerySecurityDescriptorInfo(IN PVOID Object,
|
|||
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
|
||||
|
||||
/* Get the SD */
|
||||
ObjectSd = ObpReferenceCachedSecurityDescriptor(ObjectHeader->SecurityDescriptor);
|
||||
ObjectSd = ObpReferenceSecurityDescriptor(ObjectHeader);
|
||||
|
||||
/* Query the information */
|
||||
Status = SeQuerySecurityDescriptorInfo(SecurityInformation,
|
||||
|
@ -91,7 +91,7 @@ ObQuerySecurityDescriptorInfo(IN PVOID Object,
|
|||
&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;
|
||||
|
@ -116,7 +116,7 @@ ObSetSecurityDescriptorInfo(IN PVOID Object,
|
|||
while (TRUE)
|
||||
{
|
||||
/* Reference the old descriptor */
|
||||
OldDescriptor = ObpReferenceCachedSecurityDescriptor(ObjectHeader->SecurityDescriptor);
|
||||
OldDescriptor = ObpReferenceSecurityDescriptor(ObjectHeader);
|
||||
NewDescriptor = OldDescriptor;
|
||||
|
||||
/* Set the SD information */
|
||||
|
@ -129,7 +129,7 @@ ObSetSecurityDescriptorInfo(IN PVOID Object,
|
|||
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);
|
||||
|
@ -144,20 +144,20 @@ ObSetSecurityDescriptorInfo(IN PVOID Object,
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
@ -585,8 +585,7 @@ ObGetObjectSecurity(IN PVOID Object,
|
|||
if (Type->TypeInfo.SecurityProcedure == SeDefaultObjectMethod)
|
||||
{
|
||||
/* Reference the descriptor */
|
||||
*SecurityDescriptor =
|
||||
ObpReferenceCachedSecurityDescriptor(Header->SecurityDescriptor);
|
||||
*SecurityDescriptor = ObpReferenceSecurityDescriptor(Header);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -678,7 +677,7 @@ ObReleaseObjectSecurity(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|||
else
|
||||
{
|
||||
/* Otherwise this means we used an internal descriptor */
|
||||
ObpDereferenceCachedSecurityDescriptor(SecurityDescriptor);
|
||||
ObDereferenceSecurityDescriptor(SecurityDescriptor, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,409 +0,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 */
|
Loading…
Reference in a new issue