Reactos
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Security Quality of Service (SQoS) implementation support
5 * COPYRIGHT: Copyright David Welch <welch@cwcom.net>
6 */
7
8/* INCLUDES *******************************************************************/
9
10#include <ntoskrnl.h>
11#define NDEBUG
12#include <debug.h>
13
14/* FUNCTIONS *******************************************************************/
15
16/**
17 * @brief
18 * Captures the security quality of service data given the object
19 * attributes from an object.
20 *
21 * @param[in] ObjectAttributes
22 * Attributes of an object where SQOS is to be retrieved. If the caller
23 * doesn't fill object attributes to the function, it automatically assumes
24 * SQOS is not present, or if, there's no SQOS present in the object attributes list
25 * of the object itself.
26 *
27 * @param[in] AccessMode
28 * Processor access mode.
29 *
30 * @param[in] PoolType
31 * The pool type for the captured SQOS to be used for allocation.
32 *
33 * @param[in] CaptureIfKernel
34 * Capture access condition. To be set to TRUE if the capture is done within the kernel,
35 * FALSE if the capture is done in a kernel mode driver or user mode otherwise.
36 *
37 * @param[out] CapturedSecurityQualityOfService
38 * The captured SQOS data from the object.
39 *
40 * @param[out] Present
41 * Returns TRUE if SQOS is present in an object, FALSE otherwise. FALSE is also immediately
42 * returned if no object attributes is given to the call.
43 *
44 * @return
45 * STATUS_SUCCESS if SQOS from the object has been fully and successfully captured. STATUS_INVALID_PARAMETER
46 * if the caller submits an invalid object attributes list. STATUS_INSUFFICIENT_RESOURCES if the function has
47 * failed to allocate some resources in the pool for the captured SQOS. A failure NTSTATUS code is returned
48 * otherwise.
49 */
50NTSTATUS
51NTAPI
52SepCaptureSecurityQualityOfService(
53 _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
54 _In_ KPROCESSOR_MODE AccessMode,
55 _In_ POOL_TYPE PoolType,
56 _In_ BOOLEAN CaptureIfKernel,
57 _Out_ PSECURITY_QUALITY_OF_SERVICE *CapturedSecurityQualityOfService,
58 _Out_ PBOOLEAN Present)
59{
60 PSECURITY_QUALITY_OF_SERVICE CapturedQos;
61 NTSTATUS Status = STATUS_SUCCESS;
62
63 PAGED_CODE();
64
65 ASSERT(CapturedSecurityQualityOfService);
66 ASSERT(Present);
67
68 if (ObjectAttributes != NULL)
69 {
70 if (AccessMode != KernelMode)
71 {
72 SECURITY_QUALITY_OF_SERVICE SafeQos;
73
74 _SEH2_TRY
75 {
76 ProbeForRead(ObjectAttributes,
77 sizeof(OBJECT_ATTRIBUTES),
78 sizeof(ULONG));
79 if (ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES))
80 {
81 if (ObjectAttributes->SecurityQualityOfService != NULL)
82 {
83 ProbeForRead(ObjectAttributes->SecurityQualityOfService,
84 sizeof(SECURITY_QUALITY_OF_SERVICE),
85 sizeof(ULONG));
86
87 if (((PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService)->Length ==
88 sizeof(SECURITY_QUALITY_OF_SERVICE))
89 {
90 /*
91 * Don't allocate memory here because ExAllocate should bugcheck
92 * the system if it's buggy, SEH would catch that! So make a local
93 * copy of the qos structure.
94 */
95 RtlCopyMemory(&SafeQos,
96 ObjectAttributes->SecurityQualityOfService,
97 sizeof(SECURITY_QUALITY_OF_SERVICE));
98 *Present = TRUE;
99 }
100 else
101 {
102 Status = STATUS_INVALID_PARAMETER;
103 }
104 }
105 else
106 {
107 *CapturedSecurityQualityOfService = NULL;
108 *Present = FALSE;
109 }
110 }
111 else
112 {
113 Status = STATUS_INVALID_PARAMETER;
114 }
115 }
116 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
117 {
118 Status = _SEH2_GetExceptionCode();
119 }
120 _SEH2_END;
121
122 if (NT_SUCCESS(Status))
123 {
124 if (*Present)
125 {
126 CapturedQos = ExAllocatePoolWithTag(PoolType,
127 sizeof(SECURITY_QUALITY_OF_SERVICE),
128 TAG_QOS);
129 if (CapturedQos != NULL)
130 {
131 RtlCopyMemory(CapturedQos,
132 &SafeQos,
133 sizeof(SECURITY_QUALITY_OF_SERVICE));
134 *CapturedSecurityQualityOfService = CapturedQos;
135 }
136 else
137 {
138 Status = STATUS_INSUFFICIENT_RESOURCES;
139 }
140 }
141 else
142 {
143 *CapturedSecurityQualityOfService = NULL;
144 }
145 }
146 }
147 else
148 {
149 if (ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES))
150 {
151 if (CaptureIfKernel)
152 {
153 if (ObjectAttributes->SecurityQualityOfService != NULL)
154 {
155 if (((PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService)->Length ==
156 sizeof(SECURITY_QUALITY_OF_SERVICE))
157 {
158 CapturedQos = ExAllocatePoolWithTag(PoolType,
159 sizeof(SECURITY_QUALITY_OF_SERVICE),
160 TAG_QOS);
161 if (CapturedQos != NULL)
162 {
163 RtlCopyMemory(CapturedQos,
164 ObjectAttributes->SecurityQualityOfService,
165 sizeof(SECURITY_QUALITY_OF_SERVICE));
166 *CapturedSecurityQualityOfService = CapturedQos;
167 *Present = TRUE;
168 }
169 else
170 {
171 Status = STATUS_INSUFFICIENT_RESOURCES;
172 }
173 }
174 else
175 {
176 Status = STATUS_INVALID_PARAMETER;
177 }
178 }
179 else
180 {
181 *CapturedSecurityQualityOfService = NULL;
182 *Present = FALSE;
183 }
184 }
185 else
186 {
187 *CapturedSecurityQualityOfService = (PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService;
188 *Present = (ObjectAttributes->SecurityQualityOfService != NULL);
189 }
190 }
191 else
192 {
193 Status = STATUS_INVALID_PARAMETER;
194 }
195 }
196 }
197 else
198 {
199 *CapturedSecurityQualityOfService = NULL;
200 *Present = FALSE;
201 }
202
203 return Status;
204}
205
206/**
207 * @brief
208 * Releases (frees) the captured SQOS data from an object in the memory pool.
209 *
210 * @param[in] CapturedSecurityQualityOfService
211 * The captured SQOS data to be released.
212 *
213 * @param[in] AccessMode
214 * Processor access mode.
215 *
216 * @param[in] CaptureIfKernel
217 * Capture access condition. To be set to TRUE if the capture is done within the kernel,
218 * FALSE if the capture is done in a kernel mode driver or user mode otherwise.
219 *
220 * @return
221 * Nothing.
222 */
223VOID
224NTAPI
225SepReleaseSecurityQualityOfService(
226 _In_opt_ PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService,
227 _In_ KPROCESSOR_MODE AccessMode,
228 _In_ BOOLEAN CaptureIfKernel)
229{
230 PAGED_CODE();
231
232 if (CapturedSecurityQualityOfService != NULL &&
233 (AccessMode != KernelMode || CaptureIfKernel))
234 {
235 ExFreePoolWithTag(CapturedSecurityQualityOfService, TAG_QOS);
236 }
237}
238
239/* EOF */