From 9d8706171359a415fb77b03c6e11e0d5821eb06a Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Fri, 16 Jul 2004 17:20:23 +0000 Subject: [PATCH] Implement security descriptor cache. svn path=/trunk/; revision=10142 --- reactos/ntoskrnl/Makefile | 23 +- reactos/ntoskrnl/include/internal/ob.h | 17 +- reactos/ntoskrnl/ob/namespc.c | 5 +- reactos/ntoskrnl/ob/object.c | 135 ++++++----- reactos/ntoskrnl/ob/sdcache.c | 312 +++++++++++++++++++++++++ reactos/ntoskrnl/ob/security.c | 29 ++- 6 files changed, 450 insertions(+), 71 deletions(-) create mode 100644 reactos/ntoskrnl/ob/sdcache.c diff --git a/reactos/ntoskrnl/Makefile b/reactos/ntoskrnl/Makefile index ddfb1eddd28..8a4523c0d6b 100644 --- a/reactos/ntoskrnl/Makefile +++ b/reactos/ntoskrnl/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.129 2004/07/02 21:02:54 royce Exp $ +# $Id: Makefile,v 1.130 2004/07/16 17:20:23 ekohl Exp $ # # ReactOS Operating System # @@ -130,7 +130,7 @@ OBJECTS_KE = \ ke/catch.o \ ke/critical.o \ ke/dpc.o \ - ke/device.o \ + ke/device.o \ ke/error.o \ ke/event.o \ ke/kqueue.o \ @@ -138,7 +138,7 @@ OBJECTS_KE = \ ke/main.o \ ke/mutex.o \ ke/process.o \ - ke/profile.o \ + ke/profile.o \ ke/queue.o \ ke/sem.o \ ke/spinlock.o \ @@ -223,9 +223,9 @@ OBJECTS_IO = \ io/timer.o \ io/vpb.o \ io/wdm.o \ + io/wmi.o \ io/xhaldisp.o \ - io/xhaldrv.o \ - io/wmi.o + io/xhaldrv.o # Object Manager (Ob) OBJECTS_OB = \ @@ -234,6 +234,7 @@ OBJECTS_OB = \ ob/namespc.o \ ob/ntobj.o \ ob/object.o \ + ob/sdcache.o \ ob/security.o \ ob/symlink.o @@ -265,12 +266,12 @@ OBJECTS_EX = \ ex/napi.o \ ex/power.o \ ex/resource.o \ - ex/rundown.o \ + ex/rundown.o \ ex/stree.o \ - ex/synch.o \ + ex/synch.o \ ex/sysinfo.o \ - ex/time.o \ - ex/util.o \ + ex/time.o \ + ex/util.o \ ex/win32k.o \ ex/work.o \ ex/zone.o @@ -359,9 +360,9 @@ OBJECTS_CC = \ # Kernel Debugger Support (Kd) OBJECTS_KD = \ kd/dlog.o \ - kd/gdbstub.o \ + kd/gdbstub.o \ kd/kdebug.o \ - kd/mda.o \ + kd/mda.o \ kd/service.o # Boot video (Inbv) diff --git a/reactos/ntoskrnl/include/internal/ob.h b/reactos/ntoskrnl/include/internal/ob.h index fc061e3bd92..e6184dcbafb 100644 --- a/reactos/ntoskrnl/include/internal/ob.h +++ b/reactos/ntoskrnl/include/internal/ob.h @@ -133,8 +133,21 @@ ObDuplicateObject(PEPROCESS SourceProcess, BOOLEAN InheritHandle, ULONG Options); -ULONG -ObpGetHandleCountbyHandleTable(PHANDLE_TABLE HandleTable); +ULONG +ObpGetHandleCountByHandleTable(PHANDLE_TABLE HandleTable); + + +/* Security descriptor cache functions */ + +NTSTATUS +ObpInitSdCache(VOID); + +NTSTATUS +ObpAddSecurityDescriptor(IN PSECURITY_DESCRIPTOR SourceSD, + OUT PSECURITY_DESCRIPTOR *DestinationSD); + +NTSTATUS +ObpRemoveSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor); #endif /* __INCLUDE_INTERNAL_OBJMGR_H */ diff --git a/reactos/ntoskrnl/ob/namespc.c b/reactos/ntoskrnl/ob/namespc.c index f374c95a6e8..0c18f2e2ec3 100644 --- a/reactos/ntoskrnl/ob/namespc.c +++ b/reactos/ntoskrnl/ob/namespc.c @@ -1,4 +1,4 @@ -/* $Id: namespc.c,v 1.44 2003/11/17 02:12:51 hyperion Exp $ +/* $Id: namespc.c,v 1.45 2004/07/16 17:19:15 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -349,6 +349,9 @@ ObInit(VOID) OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING Name; + /* Initialize the security descriptor cache */ + ObpInitSdCache(); + /* create 'directory' object type */ ObDirectoryType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE)); diff --git a/reactos/ntoskrnl/ob/object.c b/reactos/ntoskrnl/ob/object.c index 81eabe93747..a83d29e93b8 100644 --- a/reactos/ntoskrnl/ob/object.c +++ b/reactos/ntoskrnl/ob/object.c @@ -1,4 +1,4 @@ -/* $Id: object.c,v 1.77 2004/03/12 00:46:35 dwelch Exp $ +/* $Id: object.c,v 1.78 2004/07/16 17:19:15 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -36,14 +36,14 @@ typedef struct _RETENTION_CHECK_PARAMS PVOID HEADER_TO_BODY(POBJECT_HEADER obj) { - return(((char*)obj)+sizeof(OBJECT_HEADER)-sizeof(COMMON_BODY_HEADER)); + return(((char*)obj)+sizeof(OBJECT_HEADER)-sizeof(COMMON_BODY_HEADER)); } POBJECT_HEADER BODY_TO_HEADER(PVOID body) { - PCOMMON_BODY_HEADER chdr = (PCOMMON_BODY_HEADER)body; - return(CONTAINING_RECORD((&(chdr->Type)),OBJECT_HEADER,Type)); + PCOMMON_BODY_HEADER chdr = (PCOMMON_BODY_HEADER)body; + return(CONTAINING_RECORD((&(chdr->Type)),OBJECT_HEADER,Type)); } @@ -76,44 +76,44 @@ ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes, PUNICODE_STRING RemainingPath, POBJECT_TYPE ObjectType) { - PVOID NextObject; - PVOID CurrentObject; - PVOID RootObject; - POBJECT_HEADER CurrentHeader; - NTSTATUS Status; - PWSTR current; - UNICODE_STRING PathString; - ULONG Attributes; - PUNICODE_STRING ObjectName; + PVOID NextObject; + PVOID CurrentObject; + PVOID RootObject; + POBJECT_HEADER CurrentHeader; + NTSTATUS Status; + PWSTR current; + UNICODE_STRING PathString; + ULONG Attributes; + PUNICODE_STRING ObjectName; - DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, " - "RemainingPath %x)\n",ObjectAttributes,ReturnedObject,RemainingPath); - DPRINT("ObjectAttributes->ObjectName %wZ\n", - ObjectAttributes->ObjectName); + DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, " + "RemainingPath %x)\n",ObjectAttributes,ReturnedObject,RemainingPath); + DPRINT("ObjectAttributes->ObjectName %wZ\n", + ObjectAttributes->ObjectName); - RtlInitUnicodeString (RemainingPath, NULL); + RtlInitUnicodeString (RemainingPath, NULL); - if (ObjectAttributes->RootDirectory == NULL) - { - ObReferenceObjectByPointer(NameSpaceRoot, - DIRECTORY_TRAVERSE, - NULL, - UserMode); - CurrentObject = NameSpaceRoot; - } - else - { - Status = ObReferenceObjectByHandle(ObjectAttributes->RootDirectory, - DIRECTORY_TRAVERSE, - NULL, - UserMode, - &CurrentObject, - NULL); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - } + if (ObjectAttributes->RootDirectory == NULL) + { + ObReferenceObjectByPointer(NameSpaceRoot, + DIRECTORY_TRAVERSE, + NULL, + UserMode); + CurrentObject = NameSpaceRoot; + } + else + { + Status = ObReferenceObjectByHandle(ObjectAttributes->RootDirectory, + DIRECTORY_TRAVERSE, + NULL, + UserMode, + &CurrentObject, + NULL); + if (!NT_SUCCESS(Status)) + { + return Status; + } + } ObjectName = ObjectAttributes->ObjectName; if (ObjectName->Length == 0 || @@ -148,13 +148,13 @@ ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes, current = PathString.Buffer; - RootObject = CurrentObject; - Attributes = ObjectAttributes->Attributes; - if (ObjectType == ObSymbolicLinkType) - Attributes |= OBJ_OPENLINK; + RootObject = CurrentObject; + Attributes = ObjectAttributes->Attributes; + if (ObjectType == ObSymbolicLinkType) + Attributes |= OBJ_OPENLINK; - while (TRUE) - { + while (TRUE) + { DPRINT("current %S\n",current); CurrentHeader = BODY_TO_HEADER(CurrentObject); @@ -189,14 +189,14 @@ ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes, } ObDereferenceObject(CurrentObject); CurrentObject = NextObject; - } - - if (current) - RtlCreateUnicodeString (RemainingPath, current); - RtlFreeUnicodeString (&PathString); - *ReturnedObject = CurrentObject; - - return(STATUS_SUCCESS); + } + + if (current) + RtlCreateUnicodeString (RemainingPath, current); + RtlFreeUnicodeString (&PathString); + *ReturnedObject = CurrentObject; + + return STATUS_SUCCESS; } @@ -451,6 +451,30 @@ ObCreateObject (IN KPROCESSOR_MODE ObjectAttributesAccessMode OPTIONAL, } RtlFreeUnicodeString( &RemainingPath ); + if (Header->ObjectType != NULL) + { + /* FIXME: Call SeAssignSecurity() to create a new security descriptor */ + + if (Header->ObjectType->Security != NULL) + { + /* FIXME: Call the security method */ + Status = STATUS_SUCCESS; + } + else + { + /* Assign the security descriptor to the object header */ + if (ObjectAttributes != NULL && ObjectAttributes->SecurityDescriptor != NULL) + { + Status = ObpAddSecurityDescriptor(ObjectAttributes->SecurityDescriptor, + &Header->SecurityDescriptor); + } + else + { + Status = STATUS_SUCCESS; + } + } + } + if (Object != NULL) { *Object = HEADER_TO_BODY(Header); @@ -574,6 +598,11 @@ ObpDeleteObject(POBJECT_HEADER Header) KEBUGCHECK(0); } + if (Header->SecurityDescriptor != NULL) + { + ObpRemoveSecurityDescriptor(Header->SecurityDescriptor); + } + if (Header->ObjectType != NULL && Header->ObjectType->Delete != NULL) { diff --git a/reactos/ntoskrnl/ob/sdcache.c b/reactos/ntoskrnl/ob/sdcache.c new file mode 100644 index 00000000000..0b26490ce3a --- /dev/null +++ b/reactos/ntoskrnl/ob/sdcache.c @@ -0,0 +1,312 @@ +/* $Id: sdcache.c,v 1.1 2004/07/16 17:19:15 ekohl Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/kill.c + * PURPOSE: Terminating a thread + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + + +/* TYPES ********************************************************************/ + +typedef struct _SD_CACHE_ENTRY +{ + LIST_ENTRY ListEntry; + ULONG HashValue; + ULONG Index; + ULONG RefCount; +} SD_CACHE_ENTRY, *PSD_CACHE_ENTRY; + + +/* GLOBALS ******************************************************************/ + +PLIST_ENTRY ObpSdCache; +KSPIN_LOCK ObpSdCacheSpinLock; +KIRQL ObpSdCacheIrql; + + +#define SD_CACHE_ENTRIES 0x100 + +/* FUNCTIONS ****************************************************************/ + +NTSTATUS +ObpInitSdCache(VOID) +{ + ULONG i; + + ObpSdCache = ExAllocatePool(NonPagedPool, + SD_CACHE_ENTRIES * sizeof(LIST_ENTRY)); + if (ObpSdCache == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + for (i = 0; i < SD_CACHE_ENTRIES; i++) + { + InitializeListHead(&ObpSdCache[i]); + } + + KeInitializeSpinLock(&ObpSdCacheSpinLock); + + return STATUS_SUCCESS; +} + + +static VOID +ObpSdCacheLock(VOID) +{ + KeAcquireSpinLock(&ObpSdCacheSpinLock, + &ObpSdCacheIrql); +} + + +static VOID +ObpSdCacheUnlock(VOID) +{ + KeReleaseSpinLock(&ObpSdCacheSpinLock, + ObpSdCacheIrql); +} + + +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 +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 +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; +} + +/* EOF */ diff --git a/reactos/ntoskrnl/ob/security.c b/reactos/ntoskrnl/ob/security.c index d93165cda2c..b5c00dab365 100644 --- a/reactos/ntoskrnl/ob/security.c +++ b/reactos/ntoskrnl/ob/security.c @@ -56,7 +56,7 @@ ObReleaseObjectSecurity(IN PSECURITY_DESCRIPTOR SecurityDescriptor, /* - * @unimplemented + * @implemented */ NTSTATUS STDCALL NtQuerySecurityObject(IN HANDLE Handle, @@ -81,7 +81,7 @@ NtQuerySecurityObject(IN HANDLE Handle, } Header = BODY_TO_HEADER(Object); - if (Header->ObjectType != NULL && + if (Header->ObjectType == NULL && Header->ObjectType->Security != NULL) { Status = Header->ObjectType->Security(Object, @@ -93,12 +93,33 @@ NtQuerySecurityObject(IN HANDLE Handle, } else { - Status = STATUS_NOT_IMPLEMENTED; + if (Header->SecurityDescriptor != NULL) + { + /* FIXME: Use SecurityInformation */ + *ResultLength = RtlLengthSecurityDescriptor(Header->SecurityDescriptor); + if (Length >= *ResultLength) + { + RtlCopyMemory(SecurityDescriptor, + Header->SecurityDescriptor, + *ResultLength); + + Status = STATUS_SUCCESS; + } + else + { + Status = STATUS_BUFFER_TOO_SMALL; + } + } + else + { + *ResultLength = 0; + Status = STATUS_UNSUCCESSFUL; + } } ObDereferenceObject(Object); - return(Status); + return Status; } -- 2.17.1