ReactOS 0.4.15-dev-7674-gc0b4db1
objtype.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Security object type list support routines
5 * COPYRIGHT: Copyright Timo Kreuzer <timo.kreuzer@reactos.org>
6 * Copyright 2023 George Bișoc <george.bisoc@reactos.org>
7 */
8
9/* INCLUDES *******************************************************************/
10
11#include <ntoskrnl.h>
12#define NDEBUG
13#include <debug.h>
14
15/* PRIVATE FUNCTIONS **********************************************************/
16
44static
47 _In_reads_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList,
48 _In_ ULONG ObjectTypeListLength)
49{
50 PGUID ObjectTypeGuid;
51 ULONG ObjectTypeIndex;
52 USHORT Level, PrevLevel;
54
55 /* Ensure we do not hit an integer overflow */
56 Size = ObjectTypeListLength * sizeof(OBJECT_TYPE_LIST);
57 if (Size == 0)
58 {
59 DPRINT1("The object type list is too big, integer overflow alert!\n");
61 }
62
64 {
65 /* Ensure we can actually read from that list */
66 ProbeForRead(ObjectTypeList, Size, sizeof(ULONG));
67
68 /* Begin looping for each object from the list */
69 for (ObjectTypeIndex = 0;
70 ObjectTypeIndex < ObjectTypeListLength;
71 ObjectTypeIndex++)
72 {
73 /* Get the level of this object and check for validity */
74 Level = ObjectTypeList[ObjectTypeIndex].Level;
76 {
77 DPRINT1("Invalid object level found (level %u, at index %lu)\n", Level, ObjectTypeIndex);
79 }
80
81 /* Are we past the first position in the list? */
82 if (ObjectTypeIndex != 0)
83 {
84 /* Ensure that we do not have two object roots */
86 {
87 DPRINT1("This list has two roots (at index %lu)\n", ObjectTypeIndex);
89 }
90
91 /*
92 * Ensure the current level is consistent with the prior level.
93 * That means, if the previous object is the root (denoted by the
94 * level as ACCESS_OBJECT_GUID aka 0) the current object must
95 * be a child of the parent which is the root (also called a
96 * property set). Whereas a property is a sibling of the
97 * child, the property set.
98 */
99 if (Level > PrevLevel + 1)
100 {
101 DPRINT1("The object levels are not consistent (current level %u, previous level %u, at index %lu)\n",
102 Level, PrevLevel, ObjectTypeIndex);
104 }
105 }
106 else
107 {
108 /* This is the first position so the object must be the root */
110 {
111 DPRINT1("The object is not the root at first index!\n");
113 }
114 }
115
116 /* Get the object type and check that we can read from it */
117 ObjectTypeGuid = ObjectTypeList[ObjectTypeIndex].ObjectType;
118 ProbeForRead(ObjectTypeGuid, sizeof(GUID), sizeof(ULONG));
119
120 /*
121 * Cache the level, we need it to ensure the levels between
122 * the previous and the next object are consistent with each other.
123 */
124 PrevLevel = Level;
125 }
126 }
128 {
130 }
131 _SEH2_END;
132
133 return STATUS_SUCCESS;
134}
135
149static
152 _In_ CONST GUID *Guid1,
153 _In_ CONST GUID *Guid2)
154{
155 return RtlCompareMemory(Guid1, Guid2, sizeof(GUID)) == sizeof(GUID);
156}
157
158/* PUBLIC FUNCTIONS ************************************************************/
159
179PGUID
181 _In_ PACE Ace,
182 _In_ BOOLEAN IsAceDenied)
183{
184 PGUID ObjectTypeGuid = NULL;
185
186 PAGED_CODE();
187
188 /* This Ace must not be NULL */
189 ASSERT(Ace);
190
191 /* Grab the GUID based on the object type ACE header */
192 ObjectTypeGuid = IsAceDenied ? (PGUID)&((PACCESS_DENIED_OBJECT_ACE)Ace)->ObjectType :
193 (PGUID)&((PACCESS_ALLOWED_OBJECT_ACE)Ace)->ObjectType;
194 return ObjectTypeGuid;
195}
196
224 _In_reads_(ObjectTypeListLength) POBJECT_TYPE_LIST_INTERNAL ObjectTypeList,
225 _In_ ULONG ObjectTypeListLength,
226 _In_ PGUID ObjectTypeGuid,
227 _Out_ PULONG ObjectIndex)
228{
229 ULONG ObjectTypeIndex;
230 GUID ObjectTypeGuidToSearch;
231
232 PAGED_CODE();
233
234 /* Loop over the object elements */
235 for (ObjectTypeIndex = 0;
236 ObjectTypeIndex < ObjectTypeListLength;
237 ObjectTypeIndex++)
238 {
239 /* Is this the object we are searching for? */
240 ObjectTypeGuidToSearch = ObjectTypeList[ObjectTypeIndex].ObjectTypeGuid;
241 if (SepIsEqualObjectTypeGuid(ObjectTypeGuid, &ObjectTypeGuidToSearch))
242 {
243 /* Return the indext of that object to caller */
244 *ObjectIndex = ObjectTypeIndex;
245 return TRUE;
246 }
247 }
248
249 return FALSE;
250}
251
283 _In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList,
284 _In_ ULONG ObjectTypeListLength,
286 _Out_ POBJECT_TYPE_LIST_INTERNAL *CapturedObjectTypeList)
287{
289 ULONG ObjectTypeIndex;
290 SIZE_T Size;
291 PGUID ObjectTypeGuid;
292 POBJECT_TYPE_LIST_INTERNAL InternalTypeList;
293
294 PAGED_CODE();
295
296 /* We do not support that in the kernel */
298 {
300 }
301
302 /* No count elements of objects means no captured list for you */
303 if (ObjectTypeListLength == 0)
304 {
305 *CapturedObjectTypeList = NULL;
306 return STATUS_SUCCESS;
307 }
308
309 /* Check if the caller supplied a list since we have the count of elements */
310 if (ObjectTypeList == NULL)
311 {
312 DPRINT1("The caller did not provide a list of object types!\n");
314 }
315
316 /* Validate that list before we copy contents from it */
317 Status = SepValidateObjectTypeList(ObjectTypeList, ObjectTypeListLength);
318 if (!NT_SUCCESS(Status))
319 {
320 DPRINT1("SepValidateObjectTypeList failed (Status 0x%08lx)\n", Status);
321 return Status;
322 }
323
324 /* Allocate a new list */
325 Size = ObjectTypeListLength * sizeof(OBJECT_TYPE_LIST_INTERNAL);
326 InternalTypeList = ExAllocatePoolWithTag(PagedPool, Size, TAG_SEPA);
327 if (InternalTypeList == NULL)
328 {
329 DPRINT1("Failed to allocate pool memory for the object type list!\n");
331 }
332
334 {
335 /* Loop for every object element, data was already probed */
336 for (ObjectTypeIndex = 0;
337 ObjectTypeIndex < ObjectTypeListLength;
338 ObjectTypeIndex++)
339 {
340 /* Copy the object type GUID */
341 ObjectTypeGuid = ObjectTypeList[ObjectTypeIndex].ObjectType;
342 InternalTypeList[ObjectTypeIndex].ObjectTypeGuid = *ObjectTypeGuid;
343
344 /* Copy the object hierarchy level */
345 InternalTypeList[ObjectTypeIndex].Level = ObjectTypeList[ObjectTypeIndex].Level;
346
347 /* Initialize the access check rights */
348 InternalTypeList[ObjectTypeIndex].ObjectAccessRights.RemainingAccessRights = 0;
349 InternalTypeList[ObjectTypeIndex].ObjectAccessRights.GrantedAccessRights = 0;
350 InternalTypeList[ObjectTypeIndex].ObjectAccessRights.DeniedAccessRights = 0;
351 }
352
353 /* Give the captured list to caller */
354 *CapturedObjectTypeList = InternalTypeList;
355 }
357 {
358 ExFreePoolWithTag(InternalTypeList, TAG_SEPA);
359 InternalTypeList = NULL;
361 }
362 _SEH2_END;
363
364 return STATUS_SUCCESS;
365}
366
377VOID
379 _In_ _Post_invalid_ POBJECT_TYPE_LIST_INTERNAL CapturedObjectTypeList,
381{
382 PAGED_CODE();
383
384 if ((PreviousMode != KernelMode) && (CapturedObjectTypeList != NULL))
385 {
386 ExFreePoolWithTag(CapturedObjectTypeList, TAG_SEPA);
387 }
388}
389
390/* EOF */
#define PAGED_CODE()
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
GUID * PGUID
Definition: bdasup.h:12
@ Ace
Definition: card.h:12
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
#define PagedPool
Definition: env_spec_w32.h:308
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
Status
Definition: gdiplustypes.h:25
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
ObjectType
Definition: metafile.c:81
struct _ACCESS_ALLOWED_OBJECT_ACE * PACCESS_ALLOWED_OBJECT_ACE
#define _Post_invalid_
Definition: ms_sal.h:695
#define _Out_
Definition: ms_sal.h:345
#define _In_reads_opt_(size)
Definition: ms_sal.h:320
#define _In_
Definition: ms_sal.h:308
#define _In_reads_(size)
Definition: ms_sal.h:319
#define KernelMode
Definition: asm.h:34
struct _OBJECT_TYPE_LIST_INTERNAL OBJECT_TYPE_LIST_INTERNAL
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
PGUID SepGetObjectTypeGuidFromAce(_In_ PACE Ace, _In_ BOOLEAN IsAceDenied)
Captures an object type GUID from an object access control entry (ACE).
Definition: objtype.c:180
VOID SeReleaseObjectTypeList(_In_ _Post_invalid_ POBJECT_TYPE_LIST_INTERNAL CapturedObjectTypeList, _In_ KPROCESSOR_MODE PreviousMode)
Releases a buffer list of object types.
Definition: objtype.c:378
static NTSTATUS SepValidateObjectTypeList(_In_reads_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList, _In_ ULONG ObjectTypeListLength)
Validates a list of object types passed from user mode, ensuring the following conditions are met for...
Definition: objtype.c:46
NTSTATUS SeCaptureObjectTypeList(_In_reads_opt_(ObjectTypeListLength) POBJECT_TYPE_LIST ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ KPROCESSOR_MODE PreviousMode, _Out_ POBJECT_TYPE_LIST_INTERNAL *CapturedObjectTypeList)
Captures a list of object types and converts it to an internal form for use by the kernel....
Definition: objtype.c:282
static BOOLEAN SepIsEqualObjectTypeGuid(_In_ CONST GUID *Guid1, _In_ CONST GUID *Guid2)
Compares two object type GUIDs for equality.
Definition: objtype.c:151
BOOLEAN SepObjectTypeGuidInList(_In_reads_(ObjectTypeListLength) POBJECT_TYPE_LIST_INTERNAL ObjectTypeList, _In_ ULONG ObjectTypeListLength, _In_ PGUID ObjectTypeGuid, _Out_ PULONG ObjectIndex)
Searches for an object type GUID if it exists on an object type list.
Definition: objtype.c:223
#define CONST
Definition: pedump.c:81
unsigned short USHORT
Definition: pedump.c:61
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:162
#define STATUS_SUCCESS
Definition: shellext.h:65
ACCESS_MASK RemainingAccessRights
Definition: se.h:43
ACCESS_MASK DeniedAccessRights
Definition: se.h:45
ACCESS_MASK GrantedAccessRights
Definition: se.h:44
Definition: rtltypes.h:993
ACCESS_CHECK_RIGHTS ObjectAccessRights
Definition: se.h:55
#define TAG_SEPA
Definition: tag.h:156
uint32_t * PULONG
Definition: typedefs.h:59
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:56
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
#define ACCESS_MAX_LEVEL
Definition: setypes.h:865
struct _OBJECT_TYPE_LIST OBJECT_TYPE_LIST
#define ACCESS_OBJECT_GUID
Definition: setypes.h:862