Author: ion
Date: Mon Jan  8 10:51:07 2007
New Revision: 25369
URL: 
http://svn.reactos.org/svn/reactos?rev=25369&view=rev
Log:
- 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.
Modified:
    trunk/reactos/ntoskrnl/ob/oblife.c
Modified: trunk/reactos/ntoskrnl/ob/oblife.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/oblife.c?rev=2…
==============================================================================
--- trunk/reactos/ntoskrnl/ob/oblife.c (original)
+++ trunk/reactos/ntoskrnl/ob/oblife.c Mon Jan  8 10:51:07 2007
@@ -107,9 +107,6 @@
                 /* Add the SD charge too */
                 if (Header->Flags & OB_FLAG_SECURITY) PagedPoolCharge += 2048;
             }
-
-            /* FIXME: Should be returning quota */
-            DPRINT("Quotas: %lx %lx\n", PagedPoolCharge, NonPagedPoolCharge);
         }
     }
@@ -128,6 +125,9 @@
         ExFreePool(NameInfo->Name.Buffer);
         NameInfo->Name.Buffer = NULL;
     }
+
+    /* Catch invalid access */
+    Header->Type = (POBJECT_TYPE)0xBAADB0B0;
     /* Free the object using the same allocation tag */
     ExFreePoolWithTag(HeaderLocation, ObjectType->Key);
@@ -142,6 +142,7 @@
     POBJECT_TYPE ObjectType;
     POBJECT_HEADER_NAME_INFO NameInfo;
     POBJECT_HEADER_CREATOR_INFO CreatorInfo;
+    KIRQL CalloutIrql;
     PAGED_CODE();
     /* Get the header and type */
@@ -152,33 +153,32 @@
     NameInfo = OBJECT_HEADER_TO_NAME_INFO(Header);
     CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO(Header);
-    /* Lock the object type */
-    ObpEnterObjectTypeMutex(ObjectType);
-
     /* Check if the object is on a type list */
     if ((CreatorInfo) && !(IsListEmpty(&CreatorInfo->TypeList)))
     {
+        /* Lock the object type */
+        ObpEnterObjectTypeMutex(ObjectType);
+
         /* Remove the object from the type list */
         RemoveEntryList(&CreatorInfo->TypeList);
-    }
-
-    /* Release the lock */
-    ObpLeaveObjectTypeMutex(ObjectType);
+
+        /* Release the lock */
+        ObpLeaveObjectTypeMutex(ObjectType);
+    }
     /* Check if we have a name */
     if ((NameInfo) && (NameInfo->Name.Buffer))
     {
         /* Free it */
         ExFreePool(NameInfo->Name.Buffer);
-
-        /* Clean up the string so we don't try this again */
-        RtlInitUnicodeString(&NameInfo->Name, NULL);
+        RtlInitEmptyUnicodeString(&NameInfo->Name, NULL, 0);
     }
     /* Check if we have a security descriptor */
     if (Header->SecurityDescriptor)
     {
         /* Call the security procedure to delete it */
+        ObpCalloutStart(&CalloutIrql);
         ObjectType->TypeInfo.SecurityProcedure(Object,
                                                DeleteSecurityDescriptor,
                                                0,
@@ -187,13 +187,16 @@
                                                &Header->SecurityDescriptor,
                                                0,
                                                NULL);
+        ObpCalloutEnd(CalloutIrql, "Security", ObjectType, Object);
     }
     /* Check if we have a delete procedure */
     if (ObjectType->TypeInfo.DeleteProcedure)
     {
         /* Call it */
+        ObpCalloutStart(&CalloutIrql);
         ObjectType->TypeInfo.DeleteProcedure(Object);
+        ObpCalloutEnd(CalloutIrql, "Delete", ObjectType, Object);
     }
     /* Now de-allocate all object members */
@@ -256,15 +259,26 @@
     /* Get the header */
     ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObjectBody);
+
+    /* Acquire object type lock */
+    ObpEnterObjectTypeMutex(ObjectHeader->Type);
+
+    /* Check what we're doing to it */
     if (Permanent)
     {
         /* Set it to permanent */
         ObjectHeader->Flags |= OB_FLAG_PERMANENT;
+
+        /* Release the lock */
+        ObpLeaveObjectTypeMutex(ObjectHeader->Type);
     }
     else
     {
         /* Remove the flag */
         ObjectHeader->Flags &= ~OB_FLAG_PERMANENT;
+
+        /* Release the lock */
+        ObpLeaveObjectTypeMutex(ObjectHeader->Type);
         /* Check if we should delete the object now */
         ObpDeleteNameCheck(ObjectBody);
@@ -623,9 +637,10 @@
     Header = ExAllocatePoolWithTag(PoolType, FinalSize + ObjectSize, Tag);
     if (!Header) return STATUS_INSUFFICIENT_RESOURCES;
-    /* Initialize quota info */
+    /* Check if we have a quota header */
     if (QuotaSize)
     {
+        /* Initialize quota info */
         QuotaInfo = (POBJECT_HEADER_QUOTA_INFO)Header;
         QuotaInfo->PagedPoolCharge = ObjectCreateInfo->PagedPoolCharge;
         QuotaInfo->NonPagedPoolCharge = ObjectCreateInfo->NonPagedPoolCharge;
@@ -634,26 +649,41 @@
         Header = (POBJECT_HEADER)(QuotaInfo + 1);
     }
-    /* Initialize Handle Info */
+    /* Check if we have a handle database header */
     if (HandleSize)
     {
+        /* Initialize Handle Info */
         HandleInfo = (POBJECT_HEADER_HANDLE_INFO)Header;
         HandleInfo->SingleEntry.HandleCount = 0;
         Header = (POBJECT_HEADER)(HandleInfo + 1);
     }
-    /* Initialize the Object Name Info */
+    /* Check if we have a name header */
     if (NameSize)
     {
+        /* Initialize the Object Name Info */
         NameInfo = (POBJECT_HEADER_NAME_INFO)Header;
         NameInfo->Name = *ObjectName;
         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);
     }
-    /* Initialize Creator Info */
+    /* Check if we have a creator header */
     if (CreatorSize)
     {
+        /* Initialize Creator Info */
         CreatorInfo = (POBJECT_HEADER_CREATOR_INFO)Header;
         CreatorInfo->CreatorBackTraceIndex = 0;
         CreatorInfo->CreatorUniqueProcess = PsGetCurrentProcessId();
@@ -739,7 +769,7 @@
     if (ObjectType)
     {
         /* Increase the number of objects of this type */
-        ObjectType->TotalNumberOfObjects++;
+        InterlockedIncrement(&ObjectType->TotalNumberOfObjects);
         /* Update the high water */
         ObjectType->HighWaterNumberOfObjects = max(ObjectType->
@@ -774,8 +804,6 @@
     POBJECT_CREATE_INFORMATION ObjectCreateInfo;
     UNICODE_STRING ObjectName;
     POBJECT_HEADER Header;
-    DPRINT("ObCreateObject(Type %p ObjectAttributes %p, Object %p)\n",
-            Type, ObjectAttributes, Object);
     /* Allocate a capture buffer */
     ObjectCreateInfo = ObpAllocateCapturedAttributes(LookasideCreateInfoList);
@@ -898,6 +926,8 @@
         if (*p++ == OBJ_NAME_PATH_SEPARATOR) return STATUS_OBJECT_NAME_INVALID;
     }
+    Context.Object = NULL;
+
     /* Check if we've already created the directory of types */
     if (ObpTypeDirectoryObject)
     {
@@ -911,6 +941,7 @@
                                     &Context))
         {
             /* We have already created it, so fail */
+            Context.Object = NULL;
             return STATUS_OBJECT_NAME_COLLISION;
         }
     }
@@ -922,6 +953,7 @@
     if (!ObjectName.Buffer)
     {
         /* Out of memory, fail */
+        Context.Object = NULL;
         return STATUS_INSUFFICIENT_RESOURCES;
     }
@@ -938,6 +970,8 @@
                                (POBJECT_HEADER*)&Header);
     if (!NT_SUCCESS(Status))
     {
+        Context.Object = NULL;
+
         /* Free the name and fail */
         ExFreePool(ObjectName.Buffer);
         return Status;
@@ -1067,12 +1101,15 @@
             ObReferenceObject(ObpTypeDirectoryObject);
         }
+        Context.Object = NULL;
+
         /* Return the object type and success */
         *ObjectType = LocalObjectType;
         return STATUS_SUCCESS;
     }
     /* If we got here, then we failed */
+    Context.Object = NULL;
     return STATUS_INSUFFICIENT_RESOURCES;
 }
@@ -1094,6 +1131,8 @@
 NTAPI
 ObMakeTemporaryObject(IN PVOID ObjectBody)
 {
+    PAGED_CODE();
+
     /* Call the internal API */
     ObpSetPermanentObject(ObjectBody, FALSE);
 }