ReactOS 0.4.15-dev-7924-g5949c20
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
23VOID
25{
26 /* Acquire the lock */
28 ExAcquirePushLockExclusive(&CacheEntry->PushLock);
29}
30
32VOID
34{
35 /* Release the lock */
36 ExReleasePushLockExclusive(&CacheEntry->PushLock);
38}
39
41VOID
43{
44 /* Acquire the lock */
46 ExAcquirePushLockShared(&CacheEntry->PushLock);
47}
48
50VOID
52{
53 /* Release the lock */
54 ExReleasePushLock(&CacheEntry->PushLock);
56}
57
58CODE_SEG("INIT")
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
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
113ULONG
114NTAPI
117{
118 /* Just hash the entire SD */
120}
121
123NTAPI
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 */
144
145 /* Return it */
146 return SdHeader;
147}
148
150NTAPI
154{
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
168PVOID
169NTAPI
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
180NTAPI
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 */
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 */
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 *--*/
254VOID
255NTAPI
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 *--*/
285VOID
286NTAPI
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*--*/
363NTAPI
365 OUT PSECURITY_DESCRIPTOR *OutputSecurityDescriptor,
366 IN ULONG RefBias)
367{
368 PSECURITY_DESCRIPTOR_HEADER SdHeader = NULL, NewHeader = NULL;
370 POB_SD_CACHE_LIST CacheEntry;
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 */
#define CODE_SEG(...)
INT Length2
Definition: FsRtlDissect.c:16
INT Length1
Definition: FsRtlDissect.c:15
unsigned char BOOLEAN
#define InterlockedIncrement
Definition: armddk.h:53
LONG NTSTATUS
Definition: precomp.h:26
Definition: bufpool.h:45
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static int Hash(const char *)
Definition: reader.c:2257
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define PagedPool
Definition: env_spec_w32.h:308
#define MAX_FAST_REFS
Definition: ex.h:133
FORCEINLINE VOID ExReleasePushLock(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1296
#define ExInitializePushLock
Definition: ex.h:1013
FORCEINLINE ULONG ExGetCountFastReference(IN EX_FAST_REF FastRef)
Definition: ex.h:588
FORCEINLINE VOID ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1036
FORCEINLINE BOOLEAN ExInsertFastReference(IN OUT PEX_FAST_REF FastRef, IN PVOID Object)
Definition: ex.h:646
FORCEINLINE VOID ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1105
FORCEINLINE PVOID ExGetObjectFastReference(IN EX_FAST_REF FastRef)
Definition: ex.h:580
FORCEINLINE VOID ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1252
FORCEINLINE EX_FAST_REF ExAcquireFastReference(IN OUT PEX_FAST_REF FastRef)
Definition: ex.h:617
GLfloat GLfloat p
Definition: glext.h:8902
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
NTSYSAPI ULONG WINAPI RtlLengthSecurityDescriptor(PSECURITY_DESCRIPTOR)
#define InterlockedExchangeAdd
Definition: interlocked.h:181
#define InterlockedCompareExchange
Definition: interlocked.h:104
_Check_return_ unsigned int __cdecl _rotl(_In_ unsigned int _Value, _In_ int _Shift)
#define RtlEqualMemory(a, b, c)
Definition: kdvm.h:18
#define KeLeaveCriticalRegion()
Definition: ke_x.h:119
#define KeEnterCriticalRegion()
Definition: ke_x.h:88
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
struct _EX_FAST_REF * PEX_FAST_REF
int Count
Definition: noreturn.cpp:7
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define ObpGetHeaderForEntry(x)
Definition: ob.h:103
#define ObpGetHeaderForSd(x)
Definition: ob.h:97
struct _SECURITY_DESCRIPTOR_HEADER SECURITY_DESCRIPTOR_HEADER
FORCEINLINE VOID ObpReleaseObjectLock(IN POBJECT_HEADER ObjectHeader)
Definition: ob_x.h:84
FORCEINLINE VOID ObpAcquireObjectLockShared(IN POBJECT_HEADER ObjectHeader)
Definition: ob_x.h:66
ULONG NTAPI ObpHash(IN PVOID Buffer, IN ULONG Length)
Definition: obsdcach.c:79
FORCEINLINE VOID ObpSdReleaseLockShared(IN POB_SD_CACHE_LIST CacheEntry)
Definition: obsdcach.c:51
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
PSECURITY_DESCRIPTOR NTAPI ObpReferenceSecurityDescriptor(IN POBJECT_HEADER ObjectHeader)
Definition: obsdcach.c:181
NTSTATUS NTAPI ObLogSecurityDescriptor(IN PSECURITY_DESCRIPTOR InputSecurityDescriptor, OUT PSECURITY_DESCRIPTOR *OutputSecurityDescriptor, IN ULONG RefBias)
Definition: obsdcach.c:364
FORCEINLINE VOID ObpSdReleaseLock(IN POB_SD_CACHE_LIST CacheEntry)
Definition: obsdcach.c:33
FORCEINLINE VOID ObpSdAcquireLockShared(IN POB_SD_CACHE_LIST CacheEntry)
Definition: obsdcach.c:42
ULONG NTAPI ObpHashSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN ULONG Length)
Definition: obsdcach.c:115
VOID NTAPI ObDereferenceSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN ULONG Count)
Definition: obsdcach.c:287
PSECURITY_DESCRIPTOR_HEADER NTAPI ObpCreateCacheEntry(IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN ULONG Length, IN ULONG FullHash, IN ULONG RefCount)
Definition: obsdcach.c:124
VOID NTAPI ObReferenceSecurityDescriptor(IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN ULONG Count)
Definition: obsdcach.c:256
#define SD_CACHE_ENTRIES
Definition: obsdcach.c:17
NTSTATUS NTAPI ObpInitSdCache(VOID)
Definition: obsdcach.c:61
OB_SD_CACHE_LIST ObsSecurityDescriptorCache[SD_CACHE_ENTRIES]
Definition: obsdcach.c:18
PVOID NTAPI ObpDestroySecurityDescriptorHeader(IN PSECURITY_DESCRIPTOR_HEADER SdHeader)
Definition: obsdcach.c:170
long LONG
Definition: pedump.c:60
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
LIST_ENTRY Head
Definition: ob.h:145
#define TAG_OB_SD_CACHE
Definition: tag.h:125
uint32_t * PULONG
Definition: typedefs.h:59
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
int32_t * PLONG
Definition: typedefs.h:58
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define ALIGN_DOWN(size, type)
Definition: umtypes.h:88
_In_ WDFCOLLECTION _In_ ULONG Index
#define FORCEINLINE
Definition: wdftypes.h:67
_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:191
_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:409