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