ReactOS  0.4.14-dev-552-g2fad488
obsdcach.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Kernel
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: ntoskrnl/ob/obsdcach.c
5  * PURPOSE: Security Descriptor Caching
6  * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14 
15 /* GLOBALS ********************************************************************/
16 
17 #define SD_CACHE_ENTRIES 0x100
19 
20 /* PRIVATE FUNCTIONS **********************************************************/
21 
23 VOID
25 {
26  /* Acquire the lock */
28  ExAcquirePushLockExclusive(&CacheEntry->PushLock);
29 }
30 
32 VOID
34 {
35  /* Release the lock */
36  ExReleasePushLockExclusive(&CacheEntry->PushLock);
38 }
39 
41 VOID
43 {
44  /* Acquire the lock */
46  ExAcquirePushLockShared(&CacheEntry->PushLock);
47 }
48 
50 VOID
52 {
53  /* Release the lock */
54  ExReleasePushLock(&CacheEntry->PushLock);
56 }
57 
58 INIT_FUNCTION
60 NTAPI
62 {
63  ULONG i;
64 
65  /* Loop each cache entry */
66  for (i = 0; i < SD_CACHE_ENTRIES; i++)
67  {
68  /* Initialize the lock and the list */
71  }
72 
73  /* Return success */
74  return STATUS_SUCCESS;
75 }
76 
77 ULONG
78 NTAPI
80  IN ULONG Length)
81 {
82  PULONG p, pp;
83  PUCHAR pb, ppb;
84  ULONG Hash = 0;
85 
86  /* Setup aligned and byte buffers */
87  p = Buffer;
88  pb = (PUCHAR)p;
89  ppb = (PUCHAR)((ULONG_PTR)Buffer + Length);
90  pp = (PULONG)ALIGN_DOWN(pb + Length, ULONG);
91 
92  /* Loop aligned data */
93  while (p < pp)
94  {
95  /* XOR-rotate */
96  Hash ^= *p++;
97  Hash = _rotl(Hash, 3);
98  }
99 
100  /* Loop non-aligned data */
101  pb = (PUCHAR)p;
102  while (pb < ppb)
103  {
104  /* XOR-rotate */
105  Hash ^= *pb++;
106  Hash = _rotl(Hash, 3);
107  }
108 
109  /* Return the hash */
110  return Hash;
111 }
112 
113 ULONG
114 NTAPI
116  IN ULONG Length)
117 {
118  /* Just hash the entire SD */
120 }
121 
123 NTAPI
125  IN ULONG Length,
126  IN ULONG FullHash,
127  IN ULONG RefCount)
128 {
129  ULONG CacheSize;
132 
133  /* Calculate the memory we'll need to allocate and allocate it */
134  CacheSize = Length + (sizeof(SECURITY_DESCRIPTOR_HEADER) - sizeof(QUAD));
135  SdHeader = ExAllocatePoolWithTag(PagedPool, CacheSize, TAG_OB_SD_CACHE);
136  if (!SdHeader) return NULL;
137 
138  /* Setup the header */
139  SdHeader->RefCount = RefCount;
140  SdHeader->FullHash = FullHash;
141 
142  /* Copy the descriptor */
143  RtlCopyMemory(&SdHeader->SecurityDescriptor, SecurityDescriptor, Length);
144 
145  /* Return it */
146  return SdHeader;
147 }
148 
149 BOOLEAN
150 NTAPI
152  IN ULONG Length1,
154 {
155  ULONG Length2;
157 
158  /* Get the length of the second SD */
160 
161  /* Compare lengths */
162  if (Length1 != Length2) return FALSE;
163 
164  /* Compare contents */
165  return RtlEqualMemory(Sd1, Sd2, Length1);
166 }
167 
168 PVOID
169 NTAPI
171 {
172  ASSERT(SdHeader->RefCount == 0);
173 
174  /* Just unlink the SD and return it back to the caller */
175  RemoveEntryList(&SdHeader->Link);
176  return SdHeader;
177 }
178 
180 NTAPI
182 {
185  PEX_FAST_REF FastRef;
186  EX_FAST_REF OldValue;
188 
189  /* Acquire a reference to the security descriptor */
190  FastRef = (PEX_FAST_REF)&ObjectHeader->SecurityDescriptor;
191  OldValue = ExAcquireFastReference(FastRef);
192 
193  /* Get the descriptor and reference count */
195  Count = ExGetCountFastReference(OldValue);
196 
197  /* Check if there's no descriptor or if there's still cached references */
198  if ((Count >= 1) || !(SecurityDescriptor))
199  {
200  /* Check if this is the last reference */
201  if (Count == 1)
202  {
203  /* Add the extra references that we'll take */
206 
207  /* Now insert them */
209  {
210  /* Undo the references since we failed */
212  -MAX_FAST_REFS);
213  }
214  }
215 
216  /* Return the SD */
217  return SecurityDescriptor;
218  }
219 
220  /* Lock the object */
221  ObpAcquireObjectLockShared(ObjectHeader);
222 
223  /* Get the object header */
226 
227  /* Do the reference */
228  InterlockedIncrement((PLONG)&SdHeader->RefCount);
229 
230  /* Release the lock and return */
231  ObpReleaseObjectLock(ObjectHeader);
232  return SecurityDescriptor;
233 }
234 
235 /* PUBLIC FUNCTIONS ***********************************************************/
236 
237 /*++
238  * @name ObReferenceSecurityDescriptor
239  * @implemented NT5.2
240  *
241  * The ObReferenceSecurityDescriptor routine <FILLMEIN>
242  *
243  * @param SecurityDescriptor
244  * <FILLMEIN>
245  *
246  * @param Count
247  * <FILLMEIN>
248  *
249  * @return STATUS_SUCCESS or appropriate error value.
250  *
251  * @remarks None.
252  *
253  *--*/
254 VOID
255 NTAPI
257  IN ULONG Count)
258 {
260 
261  /* Get the header */
263 
264  /* Do the references */
266 }
267 
268 /*++
269  * @name ObDereferenceSecurityDescriptor
270  * @implemented NT5.2
271  *
272  * The ObDereferenceSecurityDescriptor routine <FILLMEIN>
273  *
274  * @param SecurityDescriptor
275  * <FILLMEIN>
276  *
277  * @param Count
278  * <FILLMEIN>
279  *
280  * @return STATUS_SUCCESS or appropriate error value.
281  *
282  * @remarks None.
283  *
284  *--*/
285 VOID
286 NTAPI
288  IN ULONG Count)
289 {
291  LONG OldValue, NewValue;
292  ULONG Index;
293  POB_SD_CACHE_LIST CacheEntry;
294 
295  /* Get the header */
297 
298  /* Get the current reference count */
299  OldValue = SdHeader->RefCount;
300 
301  /* Check if the caller is destroying this SD -- we need the lock for that */
302  while (OldValue != Count)
303  {
304  /* He isn't, we can just try to derefeference atomically */
305  NewValue = InterlockedCompareExchange((PLONG)&SdHeader->RefCount,
306  OldValue - Count,
307  OldValue);
308  if (NewValue == OldValue) return;
309 
310  /* Try again */
311  OldValue = NewValue;
312  }
313 
314  /* At this point, we need the lock, so choose an entry */
315  Index = SdHeader->FullHash % SD_CACHE_ENTRIES;
316  CacheEntry = &ObsSecurityDescriptorCache[Index];
317 
318  /* Acquire the lock for it */
319  ObpSdAcquireLock(CacheEntry);
320  ASSERT(SdHeader->RefCount != 0);
321 
322  /* Now do the dereference */
323  if (InterlockedExchangeAdd((PLONG)&SdHeader->RefCount, -(LONG)Count) == Count)
324  {
325  /* We're down to zero -- destroy the header */
326  SdHeader = ObpDestroySecurityDescriptorHeader(SdHeader);
327 
328  /* Release the lock */
329  ObpSdReleaseLock(CacheEntry);
330 
331  /* Free the header */
332  ExFreePool(SdHeader);
333  }
334  else
335  {
336  /* Just release the lock */
337  ObpSdReleaseLock(CacheEntry);
338  }
339 
340 }
341 
342 /*++
343 * @name ObLogSecurityDescriptor
344 * @implemented NT5.2
345 *
346 * The ObLogSecurityDescriptor routine <FILLMEIN>
347 *
348 * @param InputSecurityDescriptor
349 * <FILLMEIN>
350 *
351 * @param OutputSecurityDescriptor
352 * <FILLMEIN>
353 *
354 * @param RefBias
355 * <FILLMEIN>
356 *
357 * @return STATUS_SUCCESS or appropriate error value.
358 *
359 * @remarks None.
360 *
361 *--*/
362 NTSTATUS
363 NTAPI
365  OUT PSECURITY_DESCRIPTOR *OutputSecurityDescriptor,
366  IN ULONG RefBias)
367 {
368  PSECURITY_DESCRIPTOR_HEADER SdHeader = NULL, NewHeader = NULL;
370  POB_SD_CACHE_LIST CacheEntry;
371  BOOLEAN Result;
372  PLIST_ENTRY NextEntry;
373 
374  /* Get the length */
375  Length = RtlLengthSecurityDescriptor(InputSecurityDescriptor);
376 
377  /* Get the hash */
378  Hash = ObpHashSecurityDescriptor(InputSecurityDescriptor, Length);
379 
380  /* Now select the appropriate cache entry */
382  CacheEntry = &ObsSecurityDescriptorCache[Index];
383 
384  /* Lock it shared */
385  ObpSdAcquireLockShared(CacheEntry);
386 
387  /* Start our search */
388  while (TRUE)
389  {
390  /* Reset result found */
391  Result = FALSE;
392 
393  /* Loop the hash list */
394  NextEntry = CacheEntry->Head.Flink;
395  while (NextEntry != &CacheEntry->Head)
396  {
397  /* Get the header */
398  SdHeader = ObpGetHeaderForEntry(NextEntry);
399 
400  /* Our hashes are ordered, so quickly check if we should stop now */
401  if (SdHeader->FullHash > Hash) break;
402 
403  /* We survived the quick hash check, now check for equalness */
404  if (SdHeader->FullHash == Hash)
405  {
406  /* Hashes match, now compare descriptors */
407  Result = ObpCompareSecurityDescriptors(InputSecurityDescriptor,
408  Length,
409  &SdHeader->SecurityDescriptor);
410  if (Result) break;
411  }
412 
413  /* Go to the next entry */
414  NextEntry = NextEntry->Flink;
415  }
416 
417  /* Check if we found anything */
418  if (Result)
419  {
420  /* Increment its reference count */
421  InterlockedExchangeAdd((PLONG)&SdHeader->RefCount, RefBias);
422 
423  /* Release the lock */
424  ObpSdReleaseLockShared(CacheEntry);
425 
426  /* Return the descriptor */
427  *OutputSecurityDescriptor = &SdHeader->SecurityDescriptor;
428 
429  /* Free anything that we may have had to create */
430  if (NewHeader) ExFreePoolWithTag(NewHeader, TAG_OB_SD_CACHE);
431  return STATUS_SUCCESS;
432  }
433 
434  /* Check if we got here, and didn't create a descriptor yet */
435  if (!NewHeader)
436  {
437  /* Release the lock */
438  ObpSdReleaseLockShared(CacheEntry);
439 
440  /* This should be our first time in the loop, create it */
441  NewHeader = ObpCreateCacheEntry(InputSecurityDescriptor,
442  Length,
443  Hash,
444  RefBias);
445  if (!NewHeader) return STATUS_INSUFFICIENT_RESOURCES;
446 
447  /* Now acquire the exclusive lock and we should hit the right path */
448  ObpSdAcquireLock(CacheEntry);
449  }
450  else
451  {
452  /* We have inserted the SD, we're fine now */
453  break;
454  }
455  }
456 
457  /* Okay, now let's do the insert, we should have the exclusive lock */
458  InsertTailList(NextEntry, &NewHeader->Link);
459 
460  /* Release the lock */
461  ObpSdReleaseLock(CacheEntry);
462 
463  /* Return the SD*/
464  *OutputSecurityDescriptor = &NewHeader->SecurityDescriptor;
465  return STATUS_SUCCESS;
466 }
467 
468 /* EOF */
static int Hash(const char *)
Definition: reader.c:2257
FORCEINLINE VOID ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1022
FORCEINLINE PVOID ExGetObjectFastReference(IN EX_FAST_REF FastRef)
Definition: ex.h:566
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
FORCEINLINE BOOLEAN ExInsertFastReference(IN OUT PEX_FAST_REF FastRef, IN PVOID Object)
Definition: ex.h:632
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
VOID NTAPI ObDereferenceSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN ULONG Count)
Definition: obsdcach.c:287
PVOID NTAPI ObpDestroySecurityDescriptorHeader(IN PSECURITY_DESCRIPTOR_HEADER SdHeader)
Definition: obsdcach.c:170
ULONG NTAPI ObpHash(IN PVOID Buffer, IN ULONG Length)
Definition: obsdcach.c:79
#define ObpGetHeaderForSd(x)
Definition: ob.h:87
struct _EX_FAST_REF * PEX_FAST_REF
_In_ USHORT _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR _Reserved_ ULONG _In_opt_ PVOID _In_opt_ const WSK_CLIENT_CONNECTION_DISPATCH _In_opt_ PEPROCESS _In_opt_ PETHREAD _In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor
Definition: wsk.h:182
FORCEINLINE VOID ObpReleaseObjectLock(IN POBJECT_HEADER ObjectHeader)
Definition: ob_x.h:84
unsigned char * PUCHAR
Definition: retypes.h:3
LONG NTSTATUS
Definition: precomp.h:26
FORCEINLINE VOID ObpSdAcquireLock(IN POB_SD_CACHE_LIST CacheEntry)
Definition: obsdcach.c:24
BOOLEAN NTAPI ObpCompareSecurityDescriptors(IN PSECURITY_DESCRIPTOR Sd1, IN ULONG Length1, IN PSECURITY_DESCRIPTOR Sd2)
Definition: obsdcach.c:151
INIT_FUNCTION NTSTATUS NTAPI ObpInitSdCache(VOID)
Definition: obsdcach.c:61
INT Length2
Definition: FsRtlDissect.c:16
#define InterlockedCompareExchange
Definition: interlocked.h:104
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
OB_SD_CACHE_LIST ObsSecurityDescriptorCache[SD_CACHE_ENTRIES]
Definition: obsdcach.c:18
#define InsertTailList(ListHead, Entry)
uint32_t ULONG_PTR
Definition: typedefs.h:63
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
INT Length1
Definition: FsRtlDissect.c:15
FORCEINLINE EX_FAST_REF ExAcquireFastReference(IN OUT PEX_FAST_REF FastRef)
Definition: ex.h:603
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
FORCEINLINE VOID ObpSdReleaseLockShared(IN POB_SD_CACHE_LIST CacheEntry)
Definition: obsdcach.c:51
struct _SECURITY_DESCRIPTOR_HEADER SECURITY_DESCRIPTOR_HEADER
long LONG
Definition: pedump.c:60
#define pp
Definition: hlsl.yy.c:1208
FORCEINLINE VOID ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1238
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define FORCEINLINE
Definition: ntbasedef.h:221
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
#define SD_CACHE_ENTRIES
Definition: obsdcach.c:17
#define ExInitializePushLock
Definition: ex.h:999
Definition: bufpool.h:45
PSECURITY_DESCRIPTOR NTAPI ObpReferenceSecurityDescriptor(IN POBJECT_HEADER ObjectHeader)
Definition: obsdcach.c:181
#define InterlockedExchangeAdd
Definition: interlocked.h:181
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
NTSYSAPI ULONG NTAPI RtlEqualMemory(CONST VOID *Source1, CONST VOID *Source2, ULONG Length)
#define ALIGN_DOWN(size, type)
Definition: umtypes.h:88
static const UCHAR Index[8]
Definition: usbohci.c:18
FORCEINLINE VOID ObpSdReleaseLock(IN POB_SD_CACHE_LIST CacheEntry)
Definition: obsdcach.c:33
FORCEINLINE ULONG ExGetCountFastReference(IN EX_FAST_REF FastRef)
Definition: ex.h:574
FORCEINLINE VOID ObpAcquireObjectLockShared(IN POBJECT_HEADER ObjectHeader)
Definition: ob_x.h:66
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
NTSTATUS NTAPI ObLogSecurityDescriptor(IN PSECURITY_DESCRIPTOR InputSecurityDescriptor, OUT PSECURITY_DESCRIPTOR *OutputSecurityDescriptor, IN ULONG RefBias)
Definition: obsdcach.c:364
#define KeEnterCriticalRegion()
Definition: ke_x.h:83
#define TAG_OB_SD_CACHE
Definition: tag.h:148
Definition: typedefs.h:117
FORCEINLINE VOID ExReleasePushLock(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1282
FORCEINLINE VOID ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1091
#define KeLeaveCriticalRegion()
Definition: ke_x.h:114
#define InterlockedIncrement
Definition: armddk.h:53
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
unsigned int * PULONG
Definition: retypes.h:1
NTSYSAPI ULONG WINAPI RtlLengthSecurityDescriptor(PSECURITY_DESCRIPTOR)
_Check_return_ unsigned int __cdecl _rotl(_In_ unsigned int _Value, _In_ int _Shift)
#define ObpGetHeaderForEntry(x)
Definition: ob.h:93
VOID NTAPI ObReferenceSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN ULONG Count)
Definition: obsdcach.c:256
LIST_ENTRY Head
Definition: ob.h:135
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
PSECURITY_DESCRIPTOR_HEADER NTAPI ObpCreateCacheEntry(IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN ULONG Length, IN ULONG FullHash, IN ULONG RefCount)
Definition: obsdcach.c:124
#define MAX_FAST_REFS
Definition: ex.h:128
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
GLfloat GLfloat p
Definition: glext.h:8902
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
return STATUS_SUCCESS
Definition: btrfs.c:2938
signed int * PLONG
Definition: retypes.h:5
FORCEINLINE VOID ObpSdAcquireLockShared(IN POB_SD_CACHE_LIST CacheEntry)
Definition: obsdcach.c:42
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
ULONG NTAPI ObpHashSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN ULONG Length)
Definition: obsdcach.c:115