Improve exception handling and memory safety in OB lifecycle
All checks were successful
Builds / ExectOS (amd64, release) (push) Successful in 45s
Builds / ExectOS (i686, debug) (push) Successful in 43s
Builds / ExectOS (amd64, debug) (push) Successful in 1m10s
Builds / ExectOS (i686, release) (push) Successful in 1m4s

This commit is contained in:
2026-08-17 17:07:18 +02:00
parent 392bc007a3
commit ea967b8084
2 changed files with 181 additions and 147 deletions

View File

@@ -24,19 +24,28 @@ namespace OB
public:
STATIC XTAPI XTSTATUS AllocateObject(IN POBJECT_CREATE_INFORMATION CreateInfo,
IN KPROCESSOR_MODE OwnerProcessorMode,
IN KPROCESSOR_MODE ProcessorMode,
IN POBJECT_TYPE ObjectType,
IN PUNICODE_STRING ObjectName,
IN ULONG ObjectBodySize,
OUT POBJECT_HEADER *ReturnedObjectHeader);
STATIC XTAPI XTSTATUS CreateObject(IN KPROCESSOR_MODE ProcessorMode,
IN POBJECT_TYPE ObjectType,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN KPROCESSOR_MODE OwnerProcessorMode,
IN OUT PVOID ParseContext,
IN ULONG ObjectBodySize,
IN ULONG PagedPoolCharge,
IN ULONG NonPagedPoolCharge,
OUT PVOID *Object);
STATIC XTAPI VOID DeferObjectDeletion(IN POBJECT_HEADER ObjectHeader);
STATIC XTFASTCALL LONG_PTR DereferenceObject(IN PVOID Object);
STATIC XTFASTCALL LONG_PTR DereferenceObject(IN PVOID Object,
IN ULONG Count);
STATIC XTFASTCALL LONG_PTR DereferenceObjectDeferDelete(IN PVOID Object);
STATIC XTFASTCALL VOID DereferenceObjectNameInformation(IN POBJECT_HEADER_NAME_INFO NameInfo);
STATIC XTFASTCALL POBJECT_HEADER_CREATOR_INFO GetObjectCreatorInformation(IN POBJECT_HEADER Header);
STATIC XTFASTCALL POBJECT_HEADER_NAME_INFO GetObjectNameInformation(IN POBJECT_HEADER Header);
STATIC XTFASTCALL POBJECT_HEADER_CREATOR_INFO GetObjectCreatorInformation(IN POBJECT_HEADER ObjectHeader);
STATIC XTFASTCALL POBJECT_HEADER_NAME_INFO GetObjectNameInformation(IN POBJECT_HEADER ObjectHeader);
STATIC XTAPI VOID InitializeObjectLifeCycle(VOID);
STATIC XTFASTCALL LONG_PTR ReferenceObject(IN PVOID Object);
STATIC XTFASTCALL LONG_PTR ReferenceObject(IN PVOID Object,
@@ -50,7 +59,7 @@ namespace OB
STATIC XTFASTCALL POBJECT_HEADER_NAME_INFO ReferenceObjectNameInformation(IN POBJECT_HEADER ObjectHeader);
private:
STATIC XTFASTCALL PWCH AllocateObjectName(IN ULONG Length,
STATIC XTFASTCALL PWCHAR AllocateObjectName(IN ULONG Length,
IN BOOLEAN UseLookaside,
IN OUT PUNICODE_STRING ObjectName);
STATIC XTAPI VOID CalculateOptionalHeaderSize(IN POBJECT_CREATE_INFORMATION CreateInfo,
@@ -68,15 +77,6 @@ namespace OB
IN PUNICODE_STRING ObjectName,
IN OUT PUNICODE_STRING CapturedObjectName,
IN BOOLEAN UseLookaside);
STATIC XTAPI XTSTATUS CreateObject(IN KPROCESSOR_MODE ProcessorMode,
IN POBJECT_TYPE ObjectType,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN KPROCESSOR_MODE OwnerProcessorMode,
IN OUT PVOID ParseContext,
IN ULONG ObjectBodySize,
IN ULONG PagedPoolCharge,
IN ULONG NonPagedPoolCharge,
OUT PVOID *Object);
STATIC XTAPI VOID DeleteObject(IN PVOID Object,
IN BOOLEAN CalledOnWorkerThread);
STATIC XTAPI VOID FreeObject(IN PVOID Object);

View File

@@ -15,7 +15,7 @@
* @param CreateInfo
* Supplies a pointer to the object creation information.
*
* @param OwnerProcessorMode
* @param ProcessorMode
* Supplies the processor mode that will own the object.
*
* @param ObjectType
@@ -37,7 +37,7 @@
XTAPI
XTSTATUS
OB::LifeCycle::AllocateObject(IN POBJECT_CREATE_INFORMATION CreateInfo,
IN KPROCESSOR_MODE OwnerProcessorMode,
IN KPROCESSOR_MODE ProcessorMode,
IN POBJECT_TYPE ObjectType,
IN PUNICODE_STRING ObjectName,
IN ULONG ObjectBodySize,
@@ -160,7 +160,7 @@ OB::LifeCycle::AllocateObject(IN POBJECT_CREATE_INFORMATION CreateInfo,
}
/* Check if the object is being created in kernel mode */
if(OwnerProcessorMode == KernelMode)
if(ProcessorMode == KernelMode)
{
/* Assign kernel mode ownership */
ObjectHeader->Flags |= OBJECT_FLAG_KERNEL_MODE;
@@ -229,7 +229,7 @@ OB::LifeCycle::AllocateObject(IN POBJECT_CREATE_INFORMATION CreateInfo,
* @since XT 1.0
*/
XTFASTCALL
PWCH
PWCHAR
OB::LifeCycle::AllocateObjectName(IN ULONG Length,
IN BOOLEAN UseLookaside,
IN OUT PUNICODE_STRING ObjectName)
@@ -257,12 +257,12 @@ OB::LifeCycle::AllocateObjectName(IN ULONG Length,
}
/* Initialize the Unicode string descriptor */
ObjectName->Buffer = (PWCH)Buffer;
ObjectName->Buffer = (PWCHAR)Buffer;
ObjectName->Length = (USHORT)Length;
ObjectName->MaximumLength = (USHORT)MaximumLength;
/* Return the buffer pointer */
return (PWCH)Buffer;
return (PWCHAR)Buffer;
}
/**
@@ -338,10 +338,8 @@ OB::LifeCycle::CalculateOptionalHeaderSize(IN POBJECT_CREATE_INFORMATION CreateI
}
/* Calculate the total size required for all optional headers */
Layout->TotalSize = Layout->QuotaInfoSize +
Layout->HandleInfoSize +
Layout->NameInfoSize +
Layout->CreatorInfoSize;
Layout->TotalSize = Layout->QuotaInfoSize + Layout->HandleInfoSize +
Layout->NameInfoSize + Layout->CreatorInfoSize;
}
/**
@@ -382,6 +380,7 @@ OB::LifeCycle::CaptureObjectCreateInformation(IN POBJECT_TYPE ObjectType,
IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
IN BOOLEAN UseLookaside)
{
OBJECT_ATTRIBUTES CapturedAttributes;
PSECURITY_QUALITY_OF_SERVICE SecurityQos;
PSECURITY_DESCRIPTOR SecurityDescriptor;
PUNICODE_STRING ObjectName;
@@ -395,31 +394,44 @@ OB::LifeCycle::CaptureObjectCreateInformation(IN POBJECT_TYPE ObjectType,
/* Zero out the output structure */
RTL::Memory::ZeroMemory(ObjectCreateInfo, sizeof(OBJECT_CREATE_INFORMATION));
/* Enter structured exception handler */
__try
{
/* Check if the caller supplied object attributes */
if(ObjectAttributes)
{
/* Enter structured exception handler for ObjectAttributes snapshot */
__try
{
/* Check if the request originated from user mode */
if(ProcessorMode != KernelMode)
{
/* Probe the object attributes structure */
MM::Probe::ProbeForReadStructure(ObjectAttributes, sizeof(OBJECT_ATTRIBUTES), sizeof(ULONG_PTR));
}
/* Validate structure length and verify that no unknown attributes are specified */
if((ObjectAttributes->Length != sizeof(OBJECT_ATTRIBUTES)) ||
(ObjectAttributes->Attributes & ~OBJECT_VALID_ATTRIBUTES))
{
/* Return error code */
Status = STATUS_INVALID_PARAMETER;
/* Snapshot the attributes to prevent TOCTOU and double-fetch vulnerabilities */
CapturedAttributes = *(CONST VOLATILE POBJECT_ATTRIBUTES)ObjectAttributes;
}
else
{
/* Copy the descriptor directly */
CapturedAttributes = *ObjectAttributes;
}
}
__except(RTL::Exception::SystemFilter())
{
/* Catch memory access violations */
return EXCEPTION_CODE;
}
/* Validate structure length and verify that no unknown attributes are specified */
if((CapturedAttributes.Length != sizeof(OBJECT_ATTRIBUTES)) ||
(CapturedAttributes.Attributes & ~OBJECT_VALID_ATTRIBUTES))
{
/* Return error code immediately */
return STATUS_INVALID_PARAMETER;
}
/* Capture the root directory and sanitize basic attribute flags */
ObjectCreateInfo->RootDirectory = ObjectAttributes->RootDirectory;
ObjectCreateInfo->Attributes = ObjectAttributes->Attributes & OBJECT_VALID_ATTRIBUTES;
ObjectCreateInfo->RootDirectory = CapturedAttributes.RootDirectory;
ObjectCreateInfo->Attributes = CapturedAttributes.Attributes & OBJECT_VALID_ATTRIBUTES;
/* Check if the owner works in user mode */
if(OwnerProcessorMode != KernelMode)
@@ -429,11 +441,42 @@ OB::LifeCycle::CaptureObjectCreateInformation(IN POBJECT_TYPE ObjectType,
}
/* Cache pointers for subsequent capture and validation */
ObjectName = ObjectAttributes->ObjectName;
SecurityDescriptor = ObjectAttributes->SecurityDescriptor;
SecurityQos = ObjectAttributes->SecurityQualityOfService;
ObjectName = CapturedAttributes.ObjectName;
SecurityDescriptor = CapturedAttributes.SecurityDescriptor;
SecurityQos = CapturedAttributes.SecurityQualityOfService;
/* Check if security descriptor is present */
/* Check if QoS data is available */
if(SecurityQos)
{
/* Enter structured exception handler for Security QoS snapshot */
__try
{
/* Check if the request originated from user mode */
if(ProcessorMode != KernelMode)
{
/* Probe the QoS structure */
MM::Probe::ProbeForReadStructure(SecurityQos, sizeof(SECURITY_QUALITY_OF_SERVICE), sizeof(ULONG));
/* Snapshot QoS data to prevent TOCTOU vulnerabilities */
ObjectCreateInfo->SecurityQualityOfService = *(CONST VOLATILE PSECURITY_QUALITY_OF_SERVICE)SecurityQos;
}
else
{
/* Copy QoS data directly */
ObjectCreateInfo->SecurityQualityOfService = *SecurityQos;
}
}
__except(RTL::Exception::SystemFilter())
{
/* Catch memory access violations */
return EXCEPTION_CODE;
}
/* Link the pointer */
ObjectCreateInfo->SecurityQos = &ObjectCreateInfo->SecurityQualityOfService;
}
/* Capture Security Descriptor outside of the broad SEH to avoid masking kernel bugs */
if(SecurityDescriptor)
{
/* Capture the security descriptor */
@@ -452,28 +495,6 @@ OB::LifeCycle::CaptureObjectCreateInformation(IN POBJECT_TYPE ObjectType,
ObjectCreateInfo->SecurityDescriptorCharge = SE::Descriptor::ComputeSecurityQuota(Size);
}
}
/* Check if previous operations succeeded and QoS data is available */
if(Status == STATUS_SUCCESS && SecurityQos)
{
/* Check if the request originated from user mode */
if(ProcessorMode != KernelMode)
{
/* Probe the QoS structure */
MM::Probe::ProbeForReadStructure(SecurityQos, sizeof(SECURITY_QUALITY_OF_SERVICE), sizeof(ULONG));
}
/* Copy QoS data into the local structure and link the pointer */
ObjectCreateInfo->SecurityQualityOfService = *SecurityQos;
ObjectCreateInfo->SecurityQos = &ObjectCreateInfo->SecurityQualityOfService;
}
}
}
}
__except (RTL::Exception::SystemFilter())
{
/* Catch memory access violations */
Status = EXCEPTION_CODE;
}
/* Check If all structure and security captures succeeded */
@@ -482,7 +503,7 @@ OB::LifeCycle::CaptureObjectCreateInformation(IN POBJECT_TYPE ObjectType,
/* Validate if an object name is available */
if(ObjectName)
{
/* Capture object name */
/* Capture object name (This function has its own SEH protection) */
Status = CaptureObjectName(ProcessorMode, ObjectName, CapturedObjectName, UseLookaside);
}
else
@@ -527,7 +548,7 @@ OB::LifeCycle::CaptureObjectCreateInformation(IN POBJECT_TYPE ObjectType,
* @param UseLookaside
* Indicates whether a lookaside list should be used for the buffer allocation if applicable.
*
* @return Returns STATUS_SUCCESS if the name was captured safely, or an appropriate error code.
* @return This routine returns a status code indicating the success or failure of the operation.
*
* @since XT 1.0
*/
@@ -540,8 +561,8 @@ OB::LifeCycle::CaptureObjectName(IN KPROCESSOR_MODE ProcessorMode,
{
UNICODE_STRING InputObjectName;
XTSTATUS Status;
PWCHAR Buffer;
ULONG Length;
PWCH Buffer;
/* Initialize local variables */
Buffer = NULLPTR;
@@ -570,7 +591,16 @@ OB::LifeCycle::CaptureObjectName(IN KPROCESSOR_MODE ProcessorMode,
/* Copy the descriptor */
InputObjectName = *ObjectName;
}
}
__except(RTL::Exception::SystemFilter())
{
/* Catch memory access violations */
Status = EXCEPTION_CODE;
}
/* Check if the memory probing succeeded */
if(Status == STATUS_SUCCESS)
{
/* Check if the string is not empty */
Length = InputObjectName.Length;
if(Length > 0)
@@ -591,6 +621,9 @@ OB::LifeCycle::CaptureObjectName(IN KPROCESSOR_MODE ProcessorMode,
Status = STATUS_INSUFFICIENT_RESOURCES;
}
else
{
/* Enter structural exception handler */
__try
{
/* Copy the string data into the buffer */
RTL::Memory::CopyMemory(Buffer, InputObjectName.Buffer, Length);
@@ -598,9 +631,6 @@ OB::LifeCycle::CaptureObjectName(IN KPROCESSOR_MODE ProcessorMode,
/* NULL-terminate the string */
Buffer[Length / sizeof(WCHAR)] = (WCHAR)0;
}
}
}
}
__except(RTL::Exception::SystemFilter())
{
/* Catch memory access violations */
@@ -613,6 +643,10 @@ OB::LifeCycle::CaptureObjectName(IN KPROCESSOR_MODE ProcessorMode,
FreeObjectName(CapturedObjectName);
}
}
}
}
}
}
/* Return status code */
return Status;
@@ -774,27 +808,27 @@ XTAPI
VOID
OB::LifeCycle::DeferObjectDeletion(IN POBJECT_HEADER ObjectHeader)
{
PVOID OldListHead, ActualListHead;
PVOID ListHead, OldListHead;
/* Capture the snapshot of the removal list */
OldListHead = RemoveObjectList;
/* Enter the CAS loop */
/* Process the deferred object deletion */
while(TRUE)
{
/* Link the current head to object header */
ObjectHeader->NextToFree = OldListHead;
/* Attempt to push the header to the list head */
ActualListHead = RTL::Atomic::CompareExchangePointer(&RemoveObjectList, OldListHead, ObjectHeader);
if(ActualListHead == OldListHead)
/* Push the header to the list head */
ListHead = RTL::Atomic::CompareExchangePointer(&RemoveObjectList, OldListHead, ObjectHeader);
if(ListHead == OldListHead)
{
/* Successfully pushed to the stack, break the loop */
break;
}
/* The list changed mid-flight, update the snapshot and retry */
OldListHead = ActualListHead;
OldListHead = ListHead;
}
/* Check if the list was empty */
@@ -943,23 +977,23 @@ OB::LifeCycle::DereferenceObject(IN PVOID Object,
IN ULONG Count)
{
POBJECT_HEADER ObjectHeader;
LONG_PTR NewCount;
LONG_PTR ReferenceCount;
/* Resolve the object header */
ObjectHeader = CONTAIN_RECORD(Object, OBJECT_HEADER, Body);
/* Decrement the reference count */
NewCount = RTL::Atomic::ExchangeAdd64(&ObjectHeader->PointerCount, -(LONG_PTR)(Count)) - Count;
ReferenceCount = RTL::Atomic::ExchangeAdd64(&ObjectHeader->PointerCount, -(LONG_PTR)(Count)) - Count;
/* Check for object expiration */
if(NewCount == 0)
if(ReferenceCount == 0)
{
/* Defer deletion to worker thread */
DeferObjectDeletion(ObjectHeader);
}
/* Return the updated reference count */
return NewCount;
return ReferenceCount;
}
/**
@@ -977,23 +1011,23 @@ LONG_PTR
OB::LifeCycle::DereferenceObjectDeferDelete(IN PVOID Object)
{
POBJECT_HEADER ObjectHeader;
LONG_PTR NewCount;
LONG_PTR ReferenceCount;
/* Resolve the object header */
ObjectHeader = CONTAIN_RECORD(Object, OBJECT_HEADER, Body);
/* Decrement the reference count */
NewCount = RTL::Atomic::Decrement64(&ObjectHeader->PointerCount);
ReferenceCount = RTL::Atomic::Decrement64(&ObjectHeader->PointerCount);
/* Check for object expiration */
if(NewCount == 0)
if(ReferenceCount == 0)
{
/* Defer deletion to worker thread */
DeferObjectDeletion(ObjectHeader);
}
/* Return the updated reference count */
return NewCount;
return ReferenceCount;
}
/**
@@ -1129,7 +1163,7 @@ OB::LifeCycle::FreeObject(IN PVOID Object)
/**
* Releases creation information resources and returns them back to the lookaside list.
*
* @param ObjectCreateInfo
* @param CreateInfo
* Supplies a pointer to the object creation information structure to be freed.
*
* @return This routine does not return any value.
@@ -1224,7 +1258,7 @@ OB::LifeCycle::GetObjectAllocationBase(IN POBJECT_HEADER ObjectHeader)
/**
* Retrieves the optional creator information header for a given object.
*
* @param Header
* @param ObjectHeader
* Supplies a pointer to the object's base header.
*
* @return This routine returns a pointer to the creator information, or NULLPTR if not present.
@@ -1233,23 +1267,23 @@ OB::LifeCycle::GetObjectAllocationBase(IN POBJECT_HEADER ObjectHeader)
*/
XTFASTCALL
POBJECT_HEADER_CREATOR_INFO
OB::LifeCycle::GetObjectCreatorInformation(IN POBJECT_HEADER Header)
OB::LifeCycle::GetObjectCreatorInformation(IN POBJECT_HEADER ObjectHeader)
{
/* Verify if the creator flag is set */
if((Header->Flags & OBJECT_FLAG_CREATOR_INFO) == 0)
if((ObjectHeader->Flags & OBJECT_FLAG_CREATOR_INFO) == 0)
{
/* Creator information not present, return NULL pounter */
return NULLPTR;
}
/* Return the creator information */
return (POBJECT_HEADER_CREATOR_INFO)((PCHAR)Header - sizeof(OBJECT_HEADER_CREATOR_INFO));
return (POBJECT_HEADER_CREATOR_INFO)((PCHAR)ObjectHeader - sizeof(OBJECT_HEADER_CREATOR_INFO));
}
/**
* Retrieves the optional name information header for a given object.
*
* @param Header
* @param ObjectHeader
* Supplies a pointer to the object's base header.
*
* @return This routine returns a pointer to the name information, or NULLPTR if not present.
@@ -1258,17 +1292,17 @@ OB::LifeCycle::GetObjectCreatorInformation(IN POBJECT_HEADER Header)
*/
XTFASTCALL
POBJECT_HEADER_NAME_INFO
OB::LifeCycle::GetObjectNameInformation(IN POBJECT_HEADER Header)
OB::LifeCycle::GetObjectNameInformation(IN POBJECT_HEADER ObjectHeader)
{
/* Check if the header is present */
if(!Header->NameInfoOffset)
if(!ObjectHeader->NameInfoOffset)
{
/* Name information not present, return NULL pointer */
return NULLPTR;
}
/* Return the name information */
return (POBJECT_HEADER_NAME_INFO)((PCHAR)Header - Header->NameInfoOffset);
return (POBJECT_HEADER_NAME_INFO)((PCHAR)ObjectHeader - ObjectHeader->NameInfoOffset);
}
/**
@@ -1333,7 +1367,7 @@ OB::LifeCycle::ProcessDeferredDeletionQueue(IN PVOID Parameter)
/* Check if the queue is still locked */
if(RemoveObjectList == OBJECT_REMOVE_QUEUE_LOCKED)
{
/* Attempt to clear the lock */
/* Clear the lock */
OldValue = RTL::Atomic::CompareExchangePointer(&RemoveObjectList, OBJECT_REMOVE_QUEUE_LOCKED, NULLPTR);
if(OldValue == OBJECT_REMOVE_QUEUE_LOCKED)
{
@@ -1426,10 +1460,10 @@ OB::LifeCycle::ReferenceObject(IN HANDLE Handle,
{
PHANDLE_TABLE_ENTRY ObjectTableEntry;
PHANDLE_TABLE_ENTRY_INFO ObjectInfo;
POBJECT_TYPE PseudoObjectType;
POBJECT_HEADER ObjectHeader;
PHANDLE_TABLE HandleTable;
ACCESS_MASK GrantedAccess;
POBJECT_TYPE PseudoType;
PVOID PseudoObject;
PEPROCESS Process;
PETHREAD Thread;
@@ -1453,19 +1487,19 @@ OB::LifeCycle::ReferenceObject(IN HANDLE Handle,
{
/* Bind the execution context to the current process pseudohandle */
PseudoObject = (PVOID)Process;
PseudoType = PS::ProcessManager::GetProcessType();
PseudoObjectType = PS::ProcessManager::GetProcessType();
GrantedAccess = Process->GrantedAccess;
}
else
{
/* Bind the execution context to the current thread pseudohandle */
PseudoObject = (PVOID)Thread;
PseudoType = PS::ProcessManager::GetThreadType();
PseudoObjectType = PS::ProcessManager::GetThreadType();
GrantedAccess = Thread->GrantedAccess;
}
/* Validate the object type */
if(ObjectType && ObjectType != PseudoType)
if(ObjectType && ObjectType != PseudoObjectType)
{
/* Object type does not match the pseudohandle type, return error code */
return STATUS_OBJECT_TYPE_MISMATCH;
@@ -1613,7 +1647,7 @@ OB::LifeCycle::ReferenceObjectNameInformation(IN POBJECT_HEADER ObjectHeader)
/* Initialize the old reference count snapshot */
OldReferences = *(volatile LONG*)&NameInfo->QueryReferences;
/* Enter the CAS loop */
/* Process the reference count */
while(TRUE)
{
/* Check if the reference count has dropped to zero */
@@ -1626,7 +1660,7 @@ OB::LifeCycle::ReferenceObjectNameInformation(IN POBJECT_HEADER ObjectHeader)
/* Calculate the incremented reference count */
NewReferences = OldReferences + 1;
/* Attempt to commit the incremented count */
/* Commit the incremented count */
ActualReferences = RTL::Atomic::CompareExchange32((PLONG)&NameInfo->QueryReferences, OldReferences, NewReferences);
if(ActualReferences == OldReferences)
{
@@ -1689,7 +1723,7 @@ OB::LifeCycle::ReleaseObjectCreateInformation(IN POBJECT_CREATE_INFORMATION Crea
*/
XTAPI
VOID
OB::LifeCycle::ReturnObjectQuota(IN POBJECT_HEADER Header,
OB::LifeCycle::ReturnObjectQuota(IN POBJECT_HEADER ObjectHeader,
IN POBJECT_TYPE ObjectType)
{
POBJECT_HEADER_QUOTA_INFO Quota;
@@ -1697,14 +1731,14 @@ OB::LifeCycle::ReturnObjectQuota(IN POBJECT_HEADER Header,
ULONG PagedPoolCharge;
/* Verify if a quota block is charged for the object */
if(!Header->QuotaBlockCharged)
if(!ObjectHeader->QuotaBlockCharged)
{
/* No quota charged, nothing to do */
return;
}
/* Retrieve the quota information header */
Quota = (POBJECT_HEADER_QUOTA_INFO)(Header->QuotaInfoOffset == 0 ? NULLPTR : ((PCHAR)Header - Header->QuotaInfoOffset));
Quota = (POBJECT_HEADER_QUOTA_INFO)(ObjectHeader->QuotaInfoOffset == 0 ? NULLPTR : ((PCHAR)ObjectHeader - ObjectHeader->QuotaInfoOffset));
if(Quota)
{
/* Extract the pool charges */
@@ -1718,7 +1752,7 @@ OB::LifeCycle::ReturnObjectQuota(IN POBJECT_HEADER Header,
PagedPoolCharge = ObjectType->TypeInfo.DefaultPagedPoolCharge;
/* Check if the object holds a default security descriptor quota */
if(Header->Flags & OBJECT_FLAG_SECURITY_QUOTA)
if(ObjectHeader->Flags & OBJECT_FLAG_SECURITY_QUOTA)
{
/* Add the default security quota to the paged pool charge */
PagedPoolCharge += SE_DEFAULT_SECURITY_QUOTA;
@@ -1726,9 +1760,9 @@ OB::LifeCycle::ReturnObjectQuota(IN POBJECT_HEADER Header,
}
/* Return the calculated pool charges */
PS::Quota::ReturnSharedPoolQuota((PEPROCESS_QUOTA_BLOCK)Header->QuotaBlockCharged,
PS::Quota::ReturnSharedPoolQuota((PEPROCESS_QUOTA_BLOCK)ObjectHeader->QuotaBlockCharged,
PagedPoolCharge, NonPagedPoolCharge);
/* Nullify the quota block pointer */
Header->QuotaBlockCharged = NULLPTR;
ObjectHeader->QuotaBlockCharged = NULLPTR;
}