xref: /reactos/ntoskrnl/se/sqos.c (revision cdf90707)
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  */
50 NTSTATUS
51 NTAPI
52 SepCaptureSecurityQualityOfService(
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  */
223 VOID
224 NTAPI
225 SepReleaseSecurityQualityOfService(
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 */
240