Improve exception handling and memory safety in OB lifecycle
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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,31 +394,44 @@ 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 */
|
|
||||||
__try
|
|
||||||
{
|
|
||||||
/* Check if the caller supplied object attributes */
|
/* Check if the caller supplied object attributes */
|
||||||
if(ObjectAttributes)
|
if(ObjectAttributes)
|
||||||
|
{
|
||||||
|
/* Enter structured exception handler for ObjectAttributes snapshot */
|
||||||
|
__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
|
||||||
{
|
{
|
||||||
|
/* 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 */
|
/* Capture the root directory and sanitize basic attribute flags */
|
||||||
ObjectCreateInfo->RootDirectory = ObjectAttributes->RootDirectory;
|
ObjectCreateInfo->RootDirectory = CapturedAttributes.RootDirectory;
|
||||||
ObjectCreateInfo->Attributes = ObjectAttributes->Attributes & OBJECT_VALID_ATTRIBUTES;
|
ObjectCreateInfo->Attributes = CapturedAttributes.Attributes & OBJECT_VALID_ATTRIBUTES;
|
||||||
|
|
||||||
/* Check if the owner works in user mode */
|
/* Check if the owner works in user mode */
|
||||||
if(OwnerProcessorMode != KernelMode)
|
if(OwnerProcessorMode != KernelMode)
|
||||||
@@ -429,11 +441,42 @@ OB::LifeCycle::CaptureObjectCreateInformation(IN POBJECT_TYPE ObjectType,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Cache pointers for subsequent capture and validation */
|
/* Cache pointers for subsequent capture and validation */
|
||||||
ObjectName = ObjectAttributes->ObjectName;
|
ObjectName = CapturedAttributes.ObjectName;
|
||||||
SecurityDescriptor = ObjectAttributes->SecurityDescriptor;
|
SecurityDescriptor = CapturedAttributes.SecurityDescriptor;
|
||||||
SecurityQos = ObjectAttributes->SecurityQualityOfService;
|
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)
|
if(SecurityDescriptor)
|
||||||
{
|
{
|
||||||
/* Capture the security descriptor */
|
/* Capture the security descriptor */
|
||||||
@@ -452,28 +495,6 @@ OB::LifeCycle::CaptureObjectCreateInformation(IN POBJECT_TYPE ObjectType,
|
|||||||
ObjectCreateInfo->SecurityDescriptorCharge = SE::Descriptor::ComputeSecurityQuota(Size);
|
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 */
|
/* 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
|
||||||
@@ -527,7 +548,7 @@ OB::LifeCycle::CaptureObjectCreateInformation(IN POBJECT_TYPE ObjectType,
|
|||||||
* @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)
|
||||||
@@ -591,6 +621,9 @@ OB::LifeCycle::CaptureObjectName(IN KPROCESSOR_MODE ProcessorMode,
|
|||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
/* Enter structural exception handler */
|
||||||
|
__try
|
||||||
{
|
{
|
||||||
/* Copy the string data into the buffer */
|
/* Copy the string data into the buffer */
|
||||||
RTL::Memory::CopyMemory(Buffer, InputObjectName.Buffer, Length);
|
RTL::Memory::CopyMemory(Buffer, InputObjectName.Buffer, Length);
|
||||||
@@ -598,9 +631,6 @@ OB::LifeCycle::CaptureObjectName(IN KPROCESSOR_MODE ProcessorMode,
|
|||||||
/* NULL-terminate the string */
|
/* NULL-terminate the string */
|
||||||
Buffer[Length / sizeof(WCHAR)] = (WCHAR)0;
|
Buffer[Length / sizeof(WCHAR)] = (WCHAR)0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
__except(RTL::Exception::SystemFilter())
|
__except(RTL::Exception::SystemFilter())
|
||||||
{
|
{
|
||||||
/* Catch memory access violations */
|
/* Catch memory access violations */
|
||||||
@@ -613,6 +643,10 @@ OB::LifeCycle::CaptureObjectName(IN KPROCESSOR_MODE ProcessorMode,
|
|||||||
FreeObjectName(CapturedObjectName);
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user