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: public:
STATIC XTAPI XTSTATUS AllocateObject(IN POBJECT_CREATE_INFORMATION CreateInfo, STATIC XTAPI XTSTATUS AllocateObject(IN POBJECT_CREATE_INFORMATION CreateInfo,
IN KPROCESSOR_MODE OwnerProcessorMode, IN KPROCESSOR_MODE ProcessorMode,
IN POBJECT_TYPE ObjectType, IN POBJECT_TYPE ObjectType,
IN PUNICODE_STRING ObjectName, IN PUNICODE_STRING ObjectName,
IN ULONG ObjectBodySize, IN ULONG ObjectBodySize,
OUT POBJECT_HEADER *ReturnedObjectHeader); 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 XTAPI VOID DeferObjectDeletion(IN POBJECT_HEADER ObjectHeader);
STATIC XTFASTCALL LONG_PTR DereferenceObject(IN PVOID Object); STATIC XTFASTCALL LONG_PTR DereferenceObject(IN PVOID Object);
STATIC XTFASTCALL LONG_PTR DereferenceObject(IN PVOID Object, STATIC XTFASTCALL LONG_PTR DereferenceObject(IN PVOID Object,
IN ULONG Count); IN ULONG Count);
STATIC XTFASTCALL LONG_PTR DereferenceObjectDeferDelete(IN PVOID Object); STATIC XTFASTCALL LONG_PTR DereferenceObjectDeferDelete(IN PVOID Object);
STATIC XTFASTCALL VOID DereferenceObjectNameInformation(IN POBJECT_HEADER_NAME_INFO NameInfo); 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_CREATOR_INFO GetObjectCreatorInformation(IN POBJECT_HEADER ObjectHeader);
STATIC XTFASTCALL POBJECT_HEADER_NAME_INFO GetObjectNameInformation(IN POBJECT_HEADER Header); STATIC XTFASTCALL POBJECT_HEADER_NAME_INFO GetObjectNameInformation(IN POBJECT_HEADER ObjectHeader);
STATIC XTAPI VOID InitializeObjectLifeCycle(VOID); STATIC XTAPI VOID InitializeObjectLifeCycle(VOID);
STATIC XTFASTCALL LONG_PTR ReferenceObject(IN PVOID Object); STATIC XTFASTCALL LONG_PTR ReferenceObject(IN PVOID Object);
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); STATIC XTFASTCALL POBJECT_HEADER_NAME_INFO ReferenceObjectNameInformation(IN POBJECT_HEADER ObjectHeader);
private: private:
STATIC XTFASTCALL PWCH AllocateObjectName(IN ULONG Length, STATIC XTFASTCALL PWCHAR AllocateObjectName(IN ULONG Length,
IN BOOLEAN UseLookaside, IN BOOLEAN UseLookaside,
IN OUT PUNICODE_STRING ObjectName); IN OUT PUNICODE_STRING ObjectName);
STATIC XTAPI VOID CalculateOptionalHeaderSize(IN POBJECT_CREATE_INFORMATION CreateInfo, STATIC XTAPI VOID CalculateOptionalHeaderSize(IN POBJECT_CREATE_INFORMATION CreateInfo,
@@ -68,15 +77,6 @@ namespace OB
IN PUNICODE_STRING ObjectName, IN PUNICODE_STRING ObjectName,
IN OUT PUNICODE_STRING CapturedObjectName, IN OUT PUNICODE_STRING CapturedObjectName,
IN BOOLEAN UseLookaside); 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, STATIC XTAPI VOID DeleteObject(IN PVOID Object,
IN BOOLEAN CalledOnWorkerThread); IN BOOLEAN CalledOnWorkerThread);
STATIC XTAPI VOID FreeObject(IN PVOID Object); STATIC XTAPI VOID FreeObject(IN PVOID Object);

View File

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