Author: ion
Date: Tue Jun 6 08:52:08 2006
New Revision: 22244
URL:
http://svn.reactos.ru/svn/reactos?rev=22244&view=rev
Log:
- Make sure callers of NtMakeTemporaryObject have DELETE privileges, otherwise they could
end up illegaly killing objects (in certain situations)
- Make sure callers of NtMakePermanentObject have SeCreatePermanentPrivilege.
- Implement ObpDeleteNameCheck as described in Gl00my's Ob Documentation (using such
documentation falls under US Reverse Engineering Law - Clean rooming).
- Remove duplicated code in ObpDecrementHandleCount and ObpSetPermanentObject and have
them use ObpDeleteNameCheck instead.
- Fixes thanks to using this routine:
* Name-check is now properly done.
* The keep-alive reference is now deleted when going from permanent->temporary
object.
* The parent directory is now dereferenced and cleared when deleting the object.
* The security procedure is now called to delete the SD, and the name buffer is freed.
- Remove ObGetObjectHandleCount, it's not a public function.
Modified:
trunk/reactos/ntoskrnl/cm/registry.c
trunk/reactos/ntoskrnl/include/internal/ob.h
trunk/reactos/ntoskrnl/ob/obhandle.c
Modified: trunk/reactos/ntoskrnl/cm/registry.c
URL:
http://svn.reactos.ru/svn/reactos/trunk/reactos/ntoskrnl/cm/registry.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/cm/registry.c (original)
+++ trunk/reactos/ntoskrnl/cm/registry.c Tue Jun 6 08:52:08 2006
@@ -23,6 +23,7 @@
#endif
#define ObGetObjectPointerCount(x) OBJECT_TO_OBJECT_HEADER(x)->PointerCount
+#define ObGetObjectHandleCount(x) OBJECT_TO_OBJECT_HEADER(x)->HandleCount
/* GLOBALS ******************************************************************/
Modified: trunk/reactos/ntoskrnl/include/internal/ob.h
URL:
http://svn.reactos.ru/svn/reactos/trunk/reactos/ntoskrnl/include/internal/o…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ob.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/ob.h Tue Jun 6 08:52:08 2006
@@ -114,9 +114,11 @@
IN PVOID Context
);
-ULONG
-NTAPI
-ObGetObjectHandleCount(PVOID Object);
+VOID
+NTAPI
+ObpDeleteNameCheck(
+ IN PVOID Object
+);
NTSTATUS
NTAPI
Modified: trunk/reactos/ntoskrnl/ob/obhandle.c
URL:
http://svn.reactos.ru/svn/reactos/trunk/reactos/ntoskrnl/ob/obhandle.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/ob/obhandle.c (original)
+++ trunk/reactos/ntoskrnl/ob/obhandle.c Tue Jun 6 08:52:08 2006
@@ -21,6 +21,70 @@
/* PRIVATE FUNCTIONS *********************************************************/
+VOID
+NTAPI
+ObpDeleteNameCheck(IN PVOID Object)
+{
+ POBJECT_HEADER ObjectHeader;
+ OBP_LOOKUP_CONTEXT Context;
+ POBJECT_HEADER_NAME_INFO ObjectNameInfo;
+ POBJECT_TYPE ObjectType;
+
+ /* Get object structures */
+ ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
+ ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
+ ObjectType = ObjectHeader->Type;
+
+ /*
+ * Check if the handle count is 0, if the object is named,
+ * and if the object isn't a permanent object.
+ */
+ if (!(ObjectHeader->HandleCount) &&
+ (ObjectNameInfo) &&
+ (ObjectNameInfo->Name.Length) &&
+ !(ObjectHeader->Flags & OB_FLAG_PERMANENT))
+ {
+ /* Make sure it's still inserted */
+ Context.Directory = ObjectNameInfo->Directory;
+ Context.DirectoryLocked = TRUE;
+ Object = ObpLookupEntryDirectory(ObjectNameInfo->Directory,
+ &ObjectNameInfo->Name,
+ 0,
+ FALSE,
+ &Context);
+ if (Object)
+ {
+ /* First delete it from the directory */
+ ObpDeleteEntryDirectory(&Context);
+
+ /* Now check if we have a security callback */
+ if (ObjectType->TypeInfo.SecurityRequired)
+ {
+ /* Call it */
+ ObjectType->TypeInfo.SecurityProcedure(Object,
+ DeleteSecurityDescriptor,
+ 0,
+ NULL,
+ NULL,
+ &ObjectHeader->
+ SecurityDescriptor,
+ ObjectType->
+ TypeInfo.PoolType,
+ NULL);
+ }
+
+ /* Free the name */
+ ExFreePool(ObjectNameInfo->Name.Buffer);
+ RtlInitEmptyUnicodeString(&ObjectNameInfo->Name, NULL, 0);
+
+ /* Clear the current directory and de-reference it */
+ ObDereferenceObject(ObjectNameInfo->Directory);
+ ObDereferenceObject(Object);
+ ObjectNameInfo->Directory = NULL;
+ }
+ }
+}
+
/*++
* @name ObpSetPermanentObject
*
@@ -43,32 +107,21 @@
IN BOOLEAN Permanent)
{
POBJECT_HEADER ObjectHeader;
- OBP_LOOKUP_CONTEXT Context;
-
+
+ /* Get the header */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObjectBody);
- ASSERT (ObjectHeader->PointerCount > 0);
if (Permanent)
{
+ /* Set it to permanent */
ObjectHeader->Flags |= OB_FLAG_PERMANENT;
}
else
{
+ /* Remove the flag */
ObjectHeader->Flags &= ~OB_FLAG_PERMANENT;
- if (ObjectHeader->HandleCount == 0 &&
- OBJECT_HEADER_TO_NAME_INFO(ObjectHeader)->Directory)
- {
- /* Make sure it's still inserted */
- Context.Directory = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader)->Directory;
- Context.DirectoryLocked = TRUE;
- if
(ObpLookupEntryDirectory(OBJECT_HEADER_TO_NAME_INFO(ObjectHeader)->Directory,
-
&OBJECT_HEADER_TO_NAME_INFO(ObjectHeader)->Name,
- 0,
- FALSE,
- &Context))
- {
- ObpDeleteEntryDirectory(&Context);
- }
- }
+
+ /* Check if we should delete the object now */
+ ObpDeleteNameCheck(ObjectBody);
}
}
@@ -113,7 +166,6 @@
{
POBJECT_HEADER ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObjectBody);
LONG NewHandleCount = InterlockedDecrement(&ObjectHeader->HandleCount);
- OBP_LOOKUP_CONTEXT Context;
DPRINT("Header: %x\n", ObjectHeader);
DPRINT("NewHandleCount: %x\n", NewHandleCount);
DPRINT("OBJECT_HEADER_TO_NAME_INFO: %x\n",
OBJECT_HEADER_TO_NAME_INFO(ObjectHeader));
@@ -126,32 +178,8 @@
ObjectHeader->Type->TypeInfo.CloseProcedure(NULL, ObjectBody, 0,
NewHandleCount + 1, NewHandleCount + 1);
}
- if(NewHandleCount == 0)
- {
- if(OBJECT_HEADER_TO_NAME_INFO(ObjectHeader) &&
- OBJECT_HEADER_TO_NAME_INFO(ObjectHeader)->Directory != NULL &&
- !(ObjectHeader->Flags & OB_FLAG_PERMANENT))
- {
- /* delete the object from the namespace when the last handle got closed.
- Only do this if it's actually been inserted into the namespace and
- if it's not a permanent object. */
-
- /* Make sure it's still inserted */
- Context.Directory = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader)->Directory;
- Context.DirectoryLocked = TRUE;
- if
(ObpLookupEntryDirectory(OBJECT_HEADER_TO_NAME_INFO(ObjectHeader)->Directory,
- &OBJECT_HEADER_TO_NAME_INFO(ObjectHeader)->Name,
- 0,
- FALSE,
- &Context))
- {
- ObpDeleteEntryDirectory(&Context);
- }
- }
-
- /* remove the keep-alive reference */
- ObDereferenceObject(ObjectBody);
- }
+ /* Check if we should delete the object */
+ ObpDeleteNameCheck(ObjectBody);
}
BOOLEAN
@@ -593,20 +621,6 @@
}
/* PUBLIC FUNCTIONS *********************************************************/
-
-ULONG
-NTAPI
-ObGetObjectHandleCount(PVOID Object)
-{
- POBJECT_HEADER Header;
-
- PAGED_CODE();
-
- ASSERT(Object);
- Header = OBJECT_TO_OBJECT_HEADER(Object);
-
- return Header->HandleCount;
-}
NTSTATUS
NTAPI
@@ -1162,18 +1176,18 @@
NTSTATUS Status;
PAGED_CODE();
+ /* Reference the object for DELETE access */
Status = ObReferenceObjectByHandle(ObjectHandle,
- 0,
+ DELETE,
NULL,
KeGetPreviousMode(),
&ObjectBody,
NULL);
if (Status != STATUS_SUCCESS) return Status;
- ObpSetPermanentObject (ObjectBody, FALSE);
-
+ /* Set it as temporary and dereference it */
+ ObpSetPermanentObject(ObjectBody, FALSE);
ObDereferenceObject(ObjectBody);
-
return STATUS_SUCCESS;
}
@@ -1197,20 +1211,26 @@
{
PVOID ObjectBody;
NTSTATUS Status;
- PAGED_CODE();
-
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ PAGED_CODE();
+
+ /* Make sure that the caller has SeCreatePermanentPrivilege */
+ Status = SeSinglePrivilegeCheck(SeCreatePermanentPrivilege,
+ PreviousMode);
+ if (!NT_SUCCESS(Status)) return STATUS_PRIVILEGE_NOT_HELD;
+
+ /* Reference the object */
Status = ObReferenceObjectByHandle(ObjectHandle,
0,
NULL,
- KeGetPreviousMode(),
+ PreviousMode,
&ObjectBody,
NULL);
if (Status != STATUS_SUCCESS) return Status;
- ObpSetPermanentObject (ObjectBody, TRUE);
-
+ /* Set it as permanent and dereference it */
+ ObpSetPermanentObject(ObjectBody, TRUE);
ObDereferenceObject(ObjectBody);
-
return STATUS_SUCCESS;
}
/* EOF */