mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 18:52:57 +00:00
- Set an invalid pointer as the object header's type when freeing it, to detect invalid usage.
- Optimize type mutex acquisition in ObpDeleteObject. Also optimize freeing of the unicode_String containing the name. Also add callout checks/protection during the security and delete procedure callouts. - Acquire object type mutex during modification of the OB_FLAG_PERMANENT flag in ObpSetPermanentObject. - Initialize default QueryReferences field to 1 during object allocation. - Support undocumented 0x10000 object attribute flag used in Windows 2003 SP1 and higher to protect objects from user-mode access (such as PhysicalMemory). - Use InterlockedIncrements for ObjectType accounting outside the type lock. - Clear the lookup context's object pointer for future use. svn path=/trunk/; revision=25369
This commit is contained in:
parent
5626181735
commit
d107f7d0f4
1 changed files with 58 additions and 19 deletions
|
@ -107,9 +107,6 @@ ObpDeallocateObject(IN PVOID Object)
|
||||||
/* Add the SD charge too */
|
/* Add the SD charge too */
|
||||||
if (Header->Flags & OB_FLAG_SECURITY) PagedPoolCharge += 2048;
|
if (Header->Flags & OB_FLAG_SECURITY) PagedPoolCharge += 2048;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Should be returning quota */
|
|
||||||
DPRINT("Quotas: %lx %lx\n", PagedPoolCharge, NonPagedPoolCharge);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,6 +126,9 @@ ObpDeallocateObject(IN PVOID Object)
|
||||||
NameInfo->Name.Buffer = NULL;
|
NameInfo->Name.Buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Catch invalid access */
|
||||||
|
Header->Type = (POBJECT_TYPE)0xBAADB0B0;
|
||||||
|
|
||||||
/* Free the object using the same allocation tag */
|
/* Free the object using the same allocation tag */
|
||||||
ExFreePoolWithTag(HeaderLocation, ObjectType->Key);
|
ExFreePoolWithTag(HeaderLocation, ObjectType->Key);
|
||||||
}
|
}
|
||||||
|
@ -142,6 +142,7 @@ ObpDeleteObject(IN PVOID Object,
|
||||||
POBJECT_TYPE ObjectType;
|
POBJECT_TYPE ObjectType;
|
||||||
POBJECT_HEADER_NAME_INFO NameInfo;
|
POBJECT_HEADER_NAME_INFO NameInfo;
|
||||||
POBJECT_HEADER_CREATOR_INFO CreatorInfo;
|
POBJECT_HEADER_CREATOR_INFO CreatorInfo;
|
||||||
|
KIRQL CalloutIrql;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
/* Get the header and type */
|
/* Get the header and type */
|
||||||
|
@ -152,33 +153,32 @@ ObpDeleteObject(IN PVOID Object,
|
||||||
NameInfo = OBJECT_HEADER_TO_NAME_INFO(Header);
|
NameInfo = OBJECT_HEADER_TO_NAME_INFO(Header);
|
||||||
CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO(Header);
|
CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO(Header);
|
||||||
|
|
||||||
/* Lock the object type */
|
|
||||||
ObpEnterObjectTypeMutex(ObjectType);
|
|
||||||
|
|
||||||
/* Check if the object is on a type list */
|
/* Check if the object is on a type list */
|
||||||
if ((CreatorInfo) && !(IsListEmpty(&CreatorInfo->TypeList)))
|
if ((CreatorInfo) && !(IsListEmpty(&CreatorInfo->TypeList)))
|
||||||
{
|
{
|
||||||
|
/* Lock the object type */
|
||||||
|
ObpEnterObjectTypeMutex(ObjectType);
|
||||||
|
|
||||||
/* Remove the object from the type list */
|
/* Remove the object from the type list */
|
||||||
RemoveEntryList(&CreatorInfo->TypeList);
|
RemoveEntryList(&CreatorInfo->TypeList);
|
||||||
}
|
|
||||||
|
|
||||||
/* Release the lock */
|
/* Release the lock */
|
||||||
ObpLeaveObjectTypeMutex(ObjectType);
|
ObpLeaveObjectTypeMutex(ObjectType);
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if we have a name */
|
/* Check if we have a name */
|
||||||
if ((NameInfo) && (NameInfo->Name.Buffer))
|
if ((NameInfo) && (NameInfo->Name.Buffer))
|
||||||
{
|
{
|
||||||
/* Free it */
|
/* Free it */
|
||||||
ExFreePool(NameInfo->Name.Buffer);
|
ExFreePool(NameInfo->Name.Buffer);
|
||||||
|
RtlInitEmptyUnicodeString(&NameInfo->Name, NULL, 0);
|
||||||
/* Clean up the string so we don't try this again */
|
|
||||||
RtlInitUnicodeString(&NameInfo->Name, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we have a security descriptor */
|
/* Check if we have a security descriptor */
|
||||||
if (Header->SecurityDescriptor)
|
if (Header->SecurityDescriptor)
|
||||||
{
|
{
|
||||||
/* Call the security procedure to delete it */
|
/* Call the security procedure to delete it */
|
||||||
|
ObpCalloutStart(&CalloutIrql);
|
||||||
ObjectType->TypeInfo.SecurityProcedure(Object,
|
ObjectType->TypeInfo.SecurityProcedure(Object,
|
||||||
DeleteSecurityDescriptor,
|
DeleteSecurityDescriptor,
|
||||||
0,
|
0,
|
||||||
|
@ -187,13 +187,16 @@ ObpDeleteObject(IN PVOID Object,
|
||||||
&Header->SecurityDescriptor,
|
&Header->SecurityDescriptor,
|
||||||
0,
|
0,
|
||||||
NULL);
|
NULL);
|
||||||
|
ObpCalloutEnd(CalloutIrql, "Security", ObjectType, Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we have a delete procedure */
|
/* Check if we have a delete procedure */
|
||||||
if (ObjectType->TypeInfo.DeleteProcedure)
|
if (ObjectType->TypeInfo.DeleteProcedure)
|
||||||
{
|
{
|
||||||
/* Call it */
|
/* Call it */
|
||||||
|
ObpCalloutStart(&CalloutIrql);
|
||||||
ObjectType->TypeInfo.DeleteProcedure(Object);
|
ObjectType->TypeInfo.DeleteProcedure(Object);
|
||||||
|
ObpCalloutEnd(CalloutIrql, "Delete", ObjectType, Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now de-allocate all object members */
|
/* Now de-allocate all object members */
|
||||||
|
@ -256,16 +259,27 @@ ObpSetPermanentObject(IN PVOID ObjectBody,
|
||||||
|
|
||||||
/* Get the header */
|
/* Get the header */
|
||||||
ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObjectBody);
|
ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObjectBody);
|
||||||
|
|
||||||
|
/* Acquire object type lock */
|
||||||
|
ObpEnterObjectTypeMutex(ObjectHeader->Type);
|
||||||
|
|
||||||
|
/* Check what we're doing to it */
|
||||||
if (Permanent)
|
if (Permanent)
|
||||||
{
|
{
|
||||||
/* Set it to permanent */
|
/* Set it to permanent */
|
||||||
ObjectHeader->Flags |= OB_FLAG_PERMANENT;
|
ObjectHeader->Flags |= OB_FLAG_PERMANENT;
|
||||||
|
|
||||||
|
/* Release the lock */
|
||||||
|
ObpLeaveObjectTypeMutex(ObjectHeader->Type);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Remove the flag */
|
/* Remove the flag */
|
||||||
ObjectHeader->Flags &= ~OB_FLAG_PERMANENT;
|
ObjectHeader->Flags &= ~OB_FLAG_PERMANENT;
|
||||||
|
|
||||||
|
/* Release the lock */
|
||||||
|
ObpLeaveObjectTypeMutex(ObjectHeader->Type);
|
||||||
|
|
||||||
/* Check if we should delete the object now */
|
/* Check if we should delete the object now */
|
||||||
ObpDeleteNameCheck(ObjectBody);
|
ObpDeleteNameCheck(ObjectBody);
|
||||||
}
|
}
|
||||||
|
@ -623,9 +637,10 @@ ObpAllocateObject(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
|
||||||
Header = ExAllocatePoolWithTag(PoolType, FinalSize + ObjectSize, Tag);
|
Header = ExAllocatePoolWithTag(PoolType, FinalSize + ObjectSize, Tag);
|
||||||
if (!Header) return STATUS_INSUFFICIENT_RESOURCES;
|
if (!Header) return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
/* Initialize quota info */
|
/* Check if we have a quota header */
|
||||||
if (QuotaSize)
|
if (QuotaSize)
|
||||||
{
|
{
|
||||||
|
/* Initialize quota info */
|
||||||
QuotaInfo = (POBJECT_HEADER_QUOTA_INFO)Header;
|
QuotaInfo = (POBJECT_HEADER_QUOTA_INFO)Header;
|
||||||
QuotaInfo->PagedPoolCharge = ObjectCreateInfo->PagedPoolCharge;
|
QuotaInfo->PagedPoolCharge = ObjectCreateInfo->PagedPoolCharge;
|
||||||
QuotaInfo->NonPagedPoolCharge = ObjectCreateInfo->NonPagedPoolCharge;
|
QuotaInfo->NonPagedPoolCharge = ObjectCreateInfo->NonPagedPoolCharge;
|
||||||
|
@ -634,26 +649,41 @@ ObpAllocateObject(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
|
||||||
Header = (POBJECT_HEADER)(QuotaInfo + 1);
|
Header = (POBJECT_HEADER)(QuotaInfo + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize Handle Info */
|
/* Check if we have a handle database header */
|
||||||
if (HandleSize)
|
if (HandleSize)
|
||||||
{
|
{
|
||||||
|
/* Initialize Handle Info */
|
||||||
HandleInfo = (POBJECT_HEADER_HANDLE_INFO)Header;
|
HandleInfo = (POBJECT_HEADER_HANDLE_INFO)Header;
|
||||||
HandleInfo->SingleEntry.HandleCount = 0;
|
HandleInfo->SingleEntry.HandleCount = 0;
|
||||||
Header = (POBJECT_HEADER)(HandleInfo + 1);
|
Header = (POBJECT_HEADER)(HandleInfo + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the Object Name Info */
|
/* Check if we have a name header */
|
||||||
if (NameSize)
|
if (NameSize)
|
||||||
{
|
{
|
||||||
|
/* Initialize the Object Name Info */
|
||||||
NameInfo = (POBJECT_HEADER_NAME_INFO)Header;
|
NameInfo = (POBJECT_HEADER_NAME_INFO)Header;
|
||||||
NameInfo->Name = *ObjectName;
|
NameInfo->Name = *ObjectName;
|
||||||
NameInfo->Directory = NULL;
|
NameInfo->Directory = NULL;
|
||||||
|
NameInfo->QueryReferences = 1;
|
||||||
|
|
||||||
|
/* Check if this is a call with the special protection flag */
|
||||||
|
if ((PreviousMode == KernelMode) &&
|
||||||
|
(ObjectCreateInfo) &&
|
||||||
|
(ObjectCreateInfo->Attributes & 0x10000))
|
||||||
|
{
|
||||||
|
/* Set flag which will make the object protected from user-mode */
|
||||||
|
NameInfo->QueryReferences |= 0x40000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the header pointer */
|
||||||
Header = (POBJECT_HEADER)(NameInfo + 1);
|
Header = (POBJECT_HEADER)(NameInfo + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize Creator Info */
|
/* Check if we have a creator header */
|
||||||
if (CreatorSize)
|
if (CreatorSize)
|
||||||
{
|
{
|
||||||
|
/* Initialize Creator Info */
|
||||||
CreatorInfo = (POBJECT_HEADER_CREATOR_INFO)Header;
|
CreatorInfo = (POBJECT_HEADER_CREATOR_INFO)Header;
|
||||||
CreatorInfo->CreatorBackTraceIndex = 0;
|
CreatorInfo->CreatorBackTraceIndex = 0;
|
||||||
CreatorInfo->CreatorUniqueProcess = PsGetCurrentProcessId();
|
CreatorInfo->CreatorUniqueProcess = PsGetCurrentProcessId();
|
||||||
|
@ -739,7 +769,7 @@ ObpAllocateObject(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
|
||||||
if (ObjectType)
|
if (ObjectType)
|
||||||
{
|
{
|
||||||
/* Increase the number of objects of this type */
|
/* Increase the number of objects of this type */
|
||||||
ObjectType->TotalNumberOfObjects++;
|
InterlockedIncrement(&ObjectType->TotalNumberOfObjects);
|
||||||
|
|
||||||
/* Update the high water */
|
/* Update the high water */
|
||||||
ObjectType->HighWaterNumberOfObjects = max(ObjectType->
|
ObjectType->HighWaterNumberOfObjects = max(ObjectType->
|
||||||
|
@ -774,8 +804,6 @@ ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL,
|
||||||
POBJECT_CREATE_INFORMATION ObjectCreateInfo;
|
POBJECT_CREATE_INFORMATION ObjectCreateInfo;
|
||||||
UNICODE_STRING ObjectName;
|
UNICODE_STRING ObjectName;
|
||||||
POBJECT_HEADER Header;
|
POBJECT_HEADER Header;
|
||||||
DPRINT("ObCreateObject(Type %p ObjectAttributes %p, Object %p)\n",
|
|
||||||
Type, ObjectAttributes, Object);
|
|
||||||
|
|
||||||
/* Allocate a capture buffer */
|
/* Allocate a capture buffer */
|
||||||
ObjectCreateInfo = ObpAllocateCapturedAttributes(LookasideCreateInfoList);
|
ObjectCreateInfo = ObpAllocateCapturedAttributes(LookasideCreateInfoList);
|
||||||
|
@ -898,6 +926,8 @@ ObCreateObjectType(IN PUNICODE_STRING TypeName,
|
||||||
if (*p++ == OBJ_NAME_PATH_SEPARATOR) return STATUS_OBJECT_NAME_INVALID;
|
if (*p++ == OBJ_NAME_PATH_SEPARATOR) return STATUS_OBJECT_NAME_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Context.Object = NULL;
|
||||||
|
|
||||||
/* Check if we've already created the directory of types */
|
/* Check if we've already created the directory of types */
|
||||||
if (ObpTypeDirectoryObject)
|
if (ObpTypeDirectoryObject)
|
||||||
{
|
{
|
||||||
|
@ -911,6 +941,7 @@ ObCreateObjectType(IN PUNICODE_STRING TypeName,
|
||||||
&Context))
|
&Context))
|
||||||
{
|
{
|
||||||
/* We have already created it, so fail */
|
/* We have already created it, so fail */
|
||||||
|
Context.Object = NULL;
|
||||||
return STATUS_OBJECT_NAME_COLLISION;
|
return STATUS_OBJECT_NAME_COLLISION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -922,6 +953,7 @@ ObCreateObjectType(IN PUNICODE_STRING TypeName,
|
||||||
if (!ObjectName.Buffer)
|
if (!ObjectName.Buffer)
|
||||||
{
|
{
|
||||||
/* Out of memory, fail */
|
/* Out of memory, fail */
|
||||||
|
Context.Object = NULL;
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -938,6 +970,8 @@ ObCreateObjectType(IN PUNICODE_STRING TypeName,
|
||||||
(POBJECT_HEADER*)&Header);
|
(POBJECT_HEADER*)&Header);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
Context.Object = NULL;
|
||||||
|
|
||||||
/* Free the name and fail */
|
/* Free the name and fail */
|
||||||
ExFreePool(ObjectName.Buffer);
|
ExFreePool(ObjectName.Buffer);
|
||||||
return Status;
|
return Status;
|
||||||
|
@ -1067,12 +1101,15 @@ ObCreateObjectType(IN PUNICODE_STRING TypeName,
|
||||||
ObReferenceObject(ObpTypeDirectoryObject);
|
ObReferenceObject(ObpTypeDirectoryObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Context.Object = NULL;
|
||||||
|
|
||||||
/* Return the object type and success */
|
/* Return the object type and success */
|
||||||
*ObjectType = LocalObjectType;
|
*ObjectType = LocalObjectType;
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we got here, then we failed */
|
/* If we got here, then we failed */
|
||||||
|
Context.Object = NULL;
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1094,6 +1131,8 @@ VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
ObMakeTemporaryObject(IN PVOID ObjectBody)
|
ObMakeTemporaryObject(IN PVOID ObjectBody)
|
||||||
{
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
/* Call the internal API */
|
/* Call the internal API */
|
||||||
ObpSetPermanentObject(ObjectBody, FALSE);
|
ObpSetPermanentObject(ObjectBody, FALSE);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue