diff --git a/ntoskrnl/include/internal/se.h b/ntoskrnl/include/internal/se.h index 03639470c72..aa01ef58088 100644 --- a/ntoskrnl/include/internal/se.h +++ b/ntoskrnl/include/internal/se.h @@ -465,20 +465,20 @@ SepDuplicateToken( NTSTATUS NTAPI SepCaptureSecurityQualityOfService( - IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, - IN KPROCESSOR_MODE AccessMode, - IN POOL_TYPE PoolType, - IN BOOLEAN CaptureIfKernel, - OUT PSECURITY_QUALITY_OF_SERVICE *CapturedSecurityQualityOfService, - OUT PBOOLEAN Present + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ KPROCESSOR_MODE AccessMode, + _In_ POOL_TYPE PoolType, + _In_ BOOLEAN CaptureIfKernel, + _Out_ PSECURITY_QUALITY_OF_SERVICE *CapturedSecurityQualityOfService, + _Out_ PBOOLEAN Present ); VOID NTAPI SepReleaseSecurityQualityOfService( - IN PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService OPTIONAL, - IN KPROCESSOR_MODE AccessMode, - IN BOOLEAN CaptureIfKernel + _In_opt_ PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService, + _In_ KPROCESSOR_MODE AccessMode, + _In_ BOOLEAN CaptureIfKernel ); NTSTATUS diff --git a/ntoskrnl/ntos.cmake b/ntoskrnl/ntos.cmake index 6e1edf2d944..4b56e74896e 100644 --- a/ntoskrnl/ntos.cmake +++ b/ntoskrnl/ntos.cmake @@ -280,6 +280,7 @@ list(APPEND SOURCE ${REACTOS_SOURCE_DIR}/ntoskrnl/se/sd.c ${REACTOS_SOURCE_DIR}/ntoskrnl/se/semgr.c ${REACTOS_SOURCE_DIR}/ntoskrnl/se/sid.c + ${REACTOS_SOURCE_DIR}/ntoskrnl/se/sqos.c ${REACTOS_SOURCE_DIR}/ntoskrnl/se/srm.c ${REACTOS_SOURCE_DIR}/ntoskrnl/se/token.c ${REACTOS_SOURCE_DIR}/ntoskrnl/vf/driver.c diff --git a/ntoskrnl/se/sd.c b/ntoskrnl/se/sd.c index 7ab6ee9d2bd..72eff599ce5 100644 --- a/ntoskrnl/se/sd.c +++ b/ntoskrnl/se/sd.c @@ -215,178 +215,6 @@ SeSetWorldSecurityDescriptor(SECURITY_INFORMATION SecurityInformation, return STATUS_SUCCESS; } - -NTSTATUS -NTAPI -SepCaptureSecurityQualityOfService(IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, - IN KPROCESSOR_MODE AccessMode, - IN POOL_TYPE PoolType, - IN BOOLEAN CaptureIfKernel, - OUT PSECURITY_QUALITY_OF_SERVICE *CapturedSecurityQualityOfService, - OUT PBOOLEAN Present) -{ - PSECURITY_QUALITY_OF_SERVICE CapturedQos; - NTSTATUS Status = STATUS_SUCCESS; - - PAGED_CODE(); - - ASSERT(CapturedSecurityQualityOfService); - ASSERT(Present); - - if (ObjectAttributes != NULL) - { - if (AccessMode != KernelMode) - { - SECURITY_QUALITY_OF_SERVICE SafeQos; - - _SEH2_TRY - { - ProbeForRead(ObjectAttributes, - sizeof(OBJECT_ATTRIBUTES), - sizeof(ULONG)); - if (ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES)) - { - if (ObjectAttributes->SecurityQualityOfService != NULL) - { - ProbeForRead(ObjectAttributes->SecurityQualityOfService, - sizeof(SECURITY_QUALITY_OF_SERVICE), - sizeof(ULONG)); - - if (((PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService)->Length == - sizeof(SECURITY_QUALITY_OF_SERVICE)) - { - /* - * Don't allocate memory here because ExAllocate should bugcheck - * the system if it's buggy, SEH would catch that! So make a local - * copy of the qos structure. - */ - RtlCopyMemory(&SafeQos, - ObjectAttributes->SecurityQualityOfService, - sizeof(SECURITY_QUALITY_OF_SERVICE)); - *Present = TRUE; - } - else - { - Status = STATUS_INVALID_PARAMETER; - } - } - else - { - *CapturedSecurityQualityOfService = NULL; - *Present = FALSE; - } - } - else - { - Status = STATUS_INVALID_PARAMETER; - } - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - Status = _SEH2_GetExceptionCode(); - } - _SEH2_END; - - if (NT_SUCCESS(Status)) - { - if (*Present) - { - CapturedQos = ExAllocatePoolWithTag(PoolType, - sizeof(SECURITY_QUALITY_OF_SERVICE), - TAG_QOS); - if (CapturedQos != NULL) - { - RtlCopyMemory(CapturedQos, - &SafeQos, - sizeof(SECURITY_QUALITY_OF_SERVICE)); - *CapturedSecurityQualityOfService = CapturedQos; - } - else - { - Status = STATUS_INSUFFICIENT_RESOURCES; - } - } - else - { - *CapturedSecurityQualityOfService = NULL; - } - } - } - else - { - if (ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES)) - { - if (CaptureIfKernel) - { - if (ObjectAttributes->SecurityQualityOfService != NULL) - { - if (((PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService)->Length == - sizeof(SECURITY_QUALITY_OF_SERVICE)) - { - CapturedQos = ExAllocatePoolWithTag(PoolType, - sizeof(SECURITY_QUALITY_OF_SERVICE), - TAG_QOS); - if (CapturedQos != NULL) - { - RtlCopyMemory(CapturedQos, - ObjectAttributes->SecurityQualityOfService, - sizeof(SECURITY_QUALITY_OF_SERVICE)); - *CapturedSecurityQualityOfService = CapturedQos; - *Present = TRUE; - } - else - { - Status = STATUS_INSUFFICIENT_RESOURCES; - } - } - else - { - Status = STATUS_INVALID_PARAMETER; - } - } - else - { - *CapturedSecurityQualityOfService = NULL; - *Present = FALSE; - } - } - else - { - *CapturedSecurityQualityOfService = (PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService; - *Present = (ObjectAttributes->SecurityQualityOfService != NULL); - } - } - else - { - Status = STATUS_INVALID_PARAMETER; - } - } - } - else - { - *CapturedSecurityQualityOfService = NULL; - *Present = FALSE; - } - - return Status; -} - - -VOID -NTAPI -SepReleaseSecurityQualityOfService(IN PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService OPTIONAL, - IN KPROCESSOR_MODE AccessMode, - IN BOOLEAN CaptureIfKernel) -{ - PAGED_CODE(); - - if (CapturedSecurityQualityOfService != NULL && - (AccessMode != KernelMode || CaptureIfKernel)) - { - ExFreePoolWithTag(CapturedSecurityQualityOfService, TAG_QOS); - } -} - /* PUBLIC FUNCTIONS ***********************************************************/ static diff --git a/ntoskrnl/se/sqos.c b/ntoskrnl/se/sqos.c new file mode 100644 index 00000000000..995c19680ba --- /dev/null +++ b/ntoskrnl/se/sqos.c @@ -0,0 +1,239 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Security Quality of Service (SQoS) implementation support + * COPYRIGHT: Copyright David Welch + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* FUNCTIONS *******************************************************************/ + +/** + * @brief + * Captures the security quality of service data given the object + * attributes from an object. + * + * @param[in] ObjectAttributes + * Attributes of an object where SQOS is to be retrieved. If the caller + * doesn't fill object attributes to the function, it automatically assumes + * SQOS is not present, or if, there's no SQOS present in the object attributes list + * of the object itself. + * + * @param[in] AccessMode + * Processor access mode. + * + * @param[in] PoolType + * The pool type for the captured SQOS to be used for allocation. + * + * @param[in] CaptureIfKernel + * Capture access condition. To be set to TRUE if the capture is done within the kernel, + * FALSE if the capture is done in a kernel mode driver or user mode otherwise. + * + * @param[out] CapturedSecurityQualityOfService + * The captured SQOS data from the object. + * + * @param[out] Present + * Returns TRUE if SQOS is present in an object, FALSE otherwise. FALSE is also immediately + * returned if no object attributes is given to the call. + * + * @return + * STATUS_SUCCESS if SQOS from the object has been fully and successfully captured. STATUS_INVALID_PARAMETER + * if the caller submits an invalid object attributes list. STATUS_INSUFFICIENT_RESOURCES if the function has + * failed to allocate some resources in the pool for the captured SQOS. A failure NTSTATUS code is returned + * otherwise. + */ +NTSTATUS +NTAPI +SepCaptureSecurityQualityOfService( + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ KPROCESSOR_MODE AccessMode, + _In_ POOL_TYPE PoolType, + _In_ BOOLEAN CaptureIfKernel, + _Out_ PSECURITY_QUALITY_OF_SERVICE *CapturedSecurityQualityOfService, + _Out_ PBOOLEAN Present) +{ + PSECURITY_QUALITY_OF_SERVICE CapturedQos; + NTSTATUS Status = STATUS_SUCCESS; + + PAGED_CODE(); + + ASSERT(CapturedSecurityQualityOfService); + ASSERT(Present); + + if (ObjectAttributes != NULL) + { + if (AccessMode != KernelMode) + { + SECURITY_QUALITY_OF_SERVICE SafeQos; + + _SEH2_TRY + { + ProbeForRead(ObjectAttributes, + sizeof(OBJECT_ATTRIBUTES), + sizeof(ULONG)); + if (ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES)) + { + if (ObjectAttributes->SecurityQualityOfService != NULL) + { + ProbeForRead(ObjectAttributes->SecurityQualityOfService, + sizeof(SECURITY_QUALITY_OF_SERVICE), + sizeof(ULONG)); + + if (((PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService)->Length == + sizeof(SECURITY_QUALITY_OF_SERVICE)) + { + /* + * Don't allocate memory here because ExAllocate should bugcheck + * the system if it's buggy, SEH would catch that! So make a local + * copy of the qos structure. + */ + RtlCopyMemory(&SafeQos, + ObjectAttributes->SecurityQualityOfService, + sizeof(SECURITY_QUALITY_OF_SERVICE)); + *Present = TRUE; + } + else + { + Status = STATUS_INVALID_PARAMETER; + } + } + else + { + *CapturedSecurityQualityOfService = NULL; + *Present = FALSE; + } + } + else + { + Status = STATUS_INVALID_PARAMETER; + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + + if (NT_SUCCESS(Status)) + { + if (*Present) + { + CapturedQos = ExAllocatePoolWithTag(PoolType, + sizeof(SECURITY_QUALITY_OF_SERVICE), + TAG_QOS); + if (CapturedQos != NULL) + { + RtlCopyMemory(CapturedQos, + &SafeQos, + sizeof(SECURITY_QUALITY_OF_SERVICE)); + *CapturedSecurityQualityOfService = CapturedQos; + } + else + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + } + else + { + *CapturedSecurityQualityOfService = NULL; + } + } + } + else + { + if (ObjectAttributes->Length == sizeof(OBJECT_ATTRIBUTES)) + { + if (CaptureIfKernel) + { + if (ObjectAttributes->SecurityQualityOfService != NULL) + { + if (((PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService)->Length == + sizeof(SECURITY_QUALITY_OF_SERVICE)) + { + CapturedQos = ExAllocatePoolWithTag(PoolType, + sizeof(SECURITY_QUALITY_OF_SERVICE), + TAG_QOS); + if (CapturedQos != NULL) + { + RtlCopyMemory(CapturedQos, + ObjectAttributes->SecurityQualityOfService, + sizeof(SECURITY_QUALITY_OF_SERVICE)); + *CapturedSecurityQualityOfService = CapturedQos; + *Present = TRUE; + } + else + { + Status = STATUS_INSUFFICIENT_RESOURCES; + } + } + else + { + Status = STATUS_INVALID_PARAMETER; + } + } + else + { + *CapturedSecurityQualityOfService = NULL; + *Present = FALSE; + } + } + else + { + *CapturedSecurityQualityOfService = (PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService; + *Present = (ObjectAttributes->SecurityQualityOfService != NULL); + } + } + else + { + Status = STATUS_INVALID_PARAMETER; + } + } + } + else + { + *CapturedSecurityQualityOfService = NULL; + *Present = FALSE; + } + + return Status; +} + +/** + * @brief + * Releases (frees) the captured SQOS data from an object in the memory pool. + * + * @param[in] CapturedSecurityQualityOfService + * The captured SQOS data to be released. + * + * @param[in] AccessMode + * Processor access mode. + * + * @param[in] CaptureIfKernel + * Capture access condition. To be set to TRUE if the capture is done within the kernel, + * FALSE if the capture is done in a kernel mode driver or user mode otherwise. + * + * @return + * Nothing. + */ +VOID +NTAPI +SepReleaseSecurityQualityOfService( + _In_opt_ PSECURITY_QUALITY_OF_SERVICE CapturedSecurityQualityOfService, + _In_ KPROCESSOR_MODE AccessMode, + _In_ BOOLEAN CaptureIfKernel) +{ + PAGED_CODE(); + + if (CapturedSecurityQualityOfService != NULL && + (AccessMode != KernelMode || CaptureIfKernel)) + { + ExFreePoolWithTag(CapturedSecurityQualityOfService, TAG_QOS); + } +} + +/* EOF */