Author: ion
Date: Mon Jan 15 21:37:53 2007
New Revision: 25467
URL:
http://svn.reactos.org/svn/reactos?rev=25467&view=rev
Log:
[22 bugfixes]:
- ObpReferenceProcessObjectByHandle is always called with HandleInformation, remove this
check.
- ObpReferenceProcessObjectByHandle already gets a process parameter, don't query the
current one.
- ObpReferenceProcessObjectByHandle already gets a handle table, don't query the
current one.
- ObpDecrementHandleCount shouldn't remove the object from the creator info.
- ObpDecrementHandleCount should clear the exclusive process if this is the last handle.
- Killing a protected handle should raise an exception if a debug port is connected, not
an exception port.
- ObpIncrementHandleCount should support OBJ_FORCE_ACCESS_CHECK.
- ObpIncrementHandleCount needs to support ObDuplicateHandle.
- ObpIncrementHandleCount needs to support being called without an AccessState.
- Fix interlocked handle count accounting.
- Allow user-mode to create kernel-mode handles.
- Fix the way Additional reference bias is de-referenced during failures.
- Complete rundown in ObKillProcess.
- Send SourceProcess in ObDuplicateHandle.
- Assume initial failure and clear handle in ObDuplicateHandle.
- Don't leak object table references when failing in ObDuplicateHandle.
- Assume failure in ObOpenObjectByName.
- Don't leak buffer during failure in ObOpenObjectByName.
- Don't leak object reference durning failure in ObOpenObjecByName.
- Validate handle attributes in ObOpenObjectByPointer.
- Use RtlCopyMemory when possible to speed up.
Modified:
trunk/reactos/ntoskrnl/ob/obhandle.c
Modified: trunk/reactos/ntoskrnl/ob/obhandle.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/obhandle.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/ob/obhandle.c (original)
+++ trunk/reactos/ntoskrnl/ob/obhandle.c Mon Jan 15 21:37:53 2007
@@ -60,14 +60,14 @@
IN PHANDLE_TABLE HandleTable,
IN KPROCESSOR_MODE AccessMode,
OUT PVOID *Object,
- OUT POBJECT_HANDLE_INFORMATION HandleInformation)
+ OUT POBJECT_HANDLE_INFORMATION HandleInformation,
+ OUT PACCESS_MASK AuditMask)
{
PHANDLE_TABLE_ENTRY HandleEntry;
POBJECT_HEADER ObjectHeader;
ACCESS_MASK GrantedAccess;
ULONG Attributes;
- PEPROCESS CurrentProcess;
- PETHREAD CurrentThread;
+ PETHREAD Thread = PsGetCurrentThread();
NTSTATUS Status;
PAGED_CODE();
@@ -77,46 +77,40 @@
/* Check if the caller wants the current process */
if (Handle == NtCurrentProcess())
{
- /* Get the current process */
- CurrentProcess = PsGetCurrentProcess();
-
- /* Check if the caller wanted handle information */
- if (HandleInformation)
- {
- /* Return it */
- HandleInformation->HandleAttributes = 0;
- HandleInformation->GrantedAccess = Process->GrantedAccess;
- }
+ /* Return handle info */
+ HandleInformation->HandleAttributes = 0;
+ HandleInformation->GrantedAccess = Process->GrantedAccess;
+
+ /* No audit mask */
+ *AuditMask = 0;
/* Reference ourselves */
- ObjectHeader = OBJECT_TO_OBJECT_HEADER(CurrentProcess);
+ ObjectHeader = OBJECT_TO_OBJECT_HEADER(Process);
InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1);
/* Return the pointer */
- *Object = CurrentProcess;
+ *Object = Process;
+ ASSERT(*Object != NULL);
return STATUS_SUCCESS;
}
/* Check if the caller wants the current thread */
if (Handle == NtCurrentThread())
{
- /* Get the current thread */
- CurrentThread = PsGetCurrentThread();
-
- /* Check if the caller wanted handle information */
- if (HandleInformation)
- {
- /* Return it */
- HandleInformation->HandleAttributes = 0;
- HandleInformation->GrantedAccess = CurrentThread->GrantedAccess;
- }
+ /* Return handle information */
+ HandleInformation->HandleAttributes = 0;
+ HandleInformation->GrantedAccess = Thread->GrantedAccess;
/* Reference ourselves */
- ObjectHeader = OBJECT_TO_OBJECT_HEADER(CurrentThread);
+ ObjectHeader = OBJECT_TO_OBJECT_HEADER(Thread);
InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1);
+ /* No audit mask */
+ *AuditMask = 0;
+
/* Return the pointer */
- *Object = CurrentThread;
+ *Object = Thread;
+ ASSERT(*Object != NULL);
return STATUS_SUCCESS;
}
@@ -126,11 +120,6 @@
/* Use the kernel handle table and get the actual handle value */
Handle = ObKernelHandleToHandle(Handle);
HandleTable = ObpKernelHandleTable;
- }
- else
- {
- /* Otherwise use this process's handle table */
- HandleTable = PsGetCurrentProcess()->ObjectTable;
}
/* Enter a critical region while we touch the handle table */
@@ -156,6 +145,9 @@
/* Fill out the information */
HandleInformation->HandleAttributes = Attributes;
HandleInformation->GrantedAccess = GrantedAccess;
+
+ /* No audit mask (FIXME!) */
+ *AuditMask = 0;
/* Return the pointer */
*Object = &ObjectHeader->Body;
@@ -244,7 +236,7 @@
if (!HandleDatabase) return NULL;
/* Copy the old database */
- RtlMoveMemory(HandleDatabase, OldHandleDatabase, OldSize);
+ RtlCopyMemory(HandleDatabase, OldHandleDatabase, OldSize);
/* Check if we he had a single entry before */
if (ObjectHeader->Flags & OB_FLAG_SINGLE_PROCESS)
@@ -440,12 +432,12 @@
POBJECT_TYPE ObjectType;
LONG SystemHandleCount, ProcessHandleCount;
LONG NewCount;
- POBJECT_HEADER_CREATOR_INFO CreatorInfo;
KIRQL CalloutIrql;
POBJECT_HEADER_HANDLE_INFO HandleInfo;
POBJECT_HANDLE_COUNT_ENTRY HandleEntry;
POBJECT_HANDLE_COUNT_DATABASE HandleDatabase;
ULONG i;
+ PAGED_CODE();
/* Get the object type and header */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObjectBody);
@@ -467,17 +459,11 @@
/* Decrement the handle count */
NewCount = InterlockedDecrement(&ObjectHeader->HandleCount);
- /* Check if we're out of handles */
- if (!NewCount)
- {
- /* Get the creator info */
- CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO(ObjectHeader);
- if ((CreatorInfo) && !(IsListEmpty(&CreatorInfo->TypeList)))
- {
- /* Remove it from the list and re-initialize it */
- RemoveEntryList(&CreatorInfo->TypeList);
- InitializeListHead(&CreatorInfo->TypeList);
- }
+ /* Check if we're out of handles and this was an exclusive object */
+ if (!(NewCount) && (ObjectHeader->Flags & OB_FLAG_EXCLUSIVE))
+ {
+ /* Clear the exclusive flag */
+ OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader)->ExclusiveProcess = NULL;
}
/* Is the object type keeping track of handles? */
@@ -644,8 +630,8 @@
/* We are! Unlock the entry */
ExUnlockHandleTableEntry(HandleTable, HandleEntry);
- /* Make sure we have an exception port */
- if (PsGetCurrentProcess()->ExceptionPort)
+ /* Make sure we have a debug port */
+ if (PsGetCurrentProcess()->DebugPort)
{
/* Raise an exception */
return KeRaiseUserException(STATUS_HANDLE_NOT_CLOSABLE);
@@ -656,10 +642,11 @@
return STATUS_HANDLE_NOT_CLOSABLE;
}
}
-
- /* Otherwise, we are kernel mode, so unlock the entry and return */
- ExUnlockHandleTableEntry(HandleTable, HandleEntry);
- return STATUS_HANDLE_NOT_CLOSABLE;
+ else
+ {
+ /* Otherwise, bugcheck the OS */
+ KeBugCheckEx(0x8B, (ULONG_PTR)Handle, 0, 0, 0);
+ }
}
/* Destroy and unlock the handle entry */
@@ -727,6 +714,8 @@
BOOLEAN Exclusive = FALSE, NewObject;
POBJECT_HEADER_CREATOR_INFO CreatorInfo;
KIRQL CalloutIrql;
+ KPROCESSOR_MODE ProbeMode;
+ ULONG Total;
/* Get the object header and type */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
@@ -738,6 +727,18 @@
OpenReason,
ObjectHeader->HandleCount,
ObjectHeader->PointerCount);
+
+ /* Check if caller is forcing user mode */
+ if (HandleAttributes & OBJ_FORCE_ACCESS_CHECK)
+ {
+ /* Force it */
+ ProbeMode = UserMode;
+ }
+ else
+ {
+ /* Keep original setting */
+ ProbeMode = AccessMode;
+ }
/* Lock the object type */
ObpEnterObjectTypeMutex(ObjectType);
@@ -797,7 +798,8 @@
}
/* Check if we're opening an existing handle */
- if (OpenReason == ObOpenHandle)
+ if ((OpenReason == ObOpenHandle) ||
+ ((OpenReason == ObDuplicateHandle) && (AccessState)))
{
/* Validate the caller's access to this object */
if (!ObCheckObjectAccess(Object,
@@ -875,7 +877,10 @@
Status = ObjectType->TypeInfo.OpenProcedure(OpenReason,
Process,
Object,
-
AccessState->PreviouslyGrantedAccess,
+ AccessState ?
+ AccessState->
+ PreviouslyGrantedAccess :
+ 0,
ProcessHandleCount);
ObpCalloutEnd(CalloutIrql, "Open", ObjectType, Object);
@@ -889,26 +894,30 @@
}
}
- /* Check if we have creator info */
- CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO(ObjectHeader);
- if (CreatorInfo)
- {
- /* We do, acquire the lock */
- ObpEnterObjectTypeMutex(ObjectType);
-
- /* Insert us on the list */
- InsertTailList(&ObjectType->TypeList, &CreatorInfo->TypeList);
-
- /* Release the lock */
- ObpLeaveObjectTypeMutex(ObjectType);
+ /* Check if this is a create operation */
+ if (OpenReason == ObCreateHandle)
+ {
+ /* Check if we have creator info */
+ CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO(ObjectHeader);
+ if (CreatorInfo)
+ {
+ /* We do, acquire the lock */
+ ObpEnterObjectTypeMutex(ObjectType);
+
+ /* Insert us on the list */
+ InsertTailList(&ObjectType->TypeList, &CreatorInfo->TypeList);
+
+ /* Release the lock */
+ ObpLeaveObjectTypeMutex(ObjectType);
+ }
}
/* Increase total number of handles */
- InterlockedIncrement((PLONG)&ObjectType->TotalNumberOfHandles);
- if (ObjectType->TotalNumberOfHandles >
ObjectType->HighWaterNumberOfHandles)
+ Total = InterlockedIncrement((PLONG)&ObjectType->TotalNumberOfHandles);
+ if (Total > ObjectType->HighWaterNumberOfHandles)
{
/* Fixup count */
- ObjectType->HighWaterNumberOfHandles = ObjectType->TotalNumberOfHandles;
+ ObjectType->HighWaterNumberOfHandles = Total;
}
/* Trace call and return */
@@ -971,6 +980,7 @@
BOOLEAN Exclusive = FALSE, NewObject;
POBJECT_HEADER_CREATOR_INFO CreatorInfo;
KIRQL CalloutIrql;
+ ULONG Total;
/* Get the object header and type */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
@@ -1123,11 +1133,11 @@
}
/* Increase total number of handles */
- InterlockedIncrement((PLONG)&ObjectType->TotalNumberOfHandles);
- if (ObjectType->TotalNumberOfHandles >
ObjectType->HighWaterNumberOfHandles)
+ Total = InterlockedIncrement((PLONG)&ObjectType->TotalNumberOfHandles);
+ if (Total > ObjectType->HighWaterNumberOfHandles)
{
/* Fixup count */
- ObjectType->HighWaterNumberOfHandles = ObjectType->TotalNumberOfHandles;
+ ObjectType->HighWaterNumberOfHandles = Total;
}
/* Trace call and return */
@@ -1208,7 +1218,7 @@
ObjectHeader->PointerCount);
/* Check if this is a kernel handle */
- if ((HandleAttributes & OBJ_KERNEL_HANDLE) && (AccessMode ==
KernelMode))
+ if (HandleAttributes & OBJ_KERNEL_HANDLE)
{
/* Set the handle table */
HandleTable = ObpKernelHandleTable;
@@ -1309,14 +1319,9 @@
}
/* Handle extra references */
- if (AdditionalReferences == 1)
- {
- /* Dereference the object once */
- ObDereferenceObject(Object);
- }
- else if (AdditionalReferences > 1)
- {
- /* Dereference it many times */
+ if (AdditionalReferences)
+ {
+ /* Dereference it as many times as required */
InterlockedExchangeAdd(&ObjectHeader->PointerCount,
-AdditionalReferences);
}
@@ -1413,7 +1418,7 @@
}
/* Check if this is a kernel handle */
- if ((HandleAttributes & OBJ_KERNEL_HANDLE) && (AccessMode ==
KernelMode))
+ if (HandleAttributes & OBJ_KERNEL_HANDLE)
{
/* Set the handle table */
HandleTable = ObpKernelHandleTable;
@@ -1508,12 +1513,6 @@
/* Make sure we got a handle */
if (Handle)
{
- /* Check if we have auxiliary data */
- if (AuxData)
- {
- /* FIXME: Change handle security */
- }
-
/* Check if this was a kernel handle */
if (KernelHandle) Handle = ObMarkHandleAsKernelHandle(Handle);
@@ -1573,16 +1572,18 @@
GrantedAccess);
/* Handle extra references */
- if (AdditionalReferences == 1)
- {
- /* Dereference the object once */
+ if (AdditionalReferences)
+ {
+ /* Check how many extra references were added */
+ if (AdditionalReferences > 1)
+ {
+ /* Dereference it many times */
+ InterlockedExchangeAdd(&ObjectHeader->PointerCount,
+ -(AdditionalReferences - 1));
+ }
+
+ /* Dereference the object one last time */
ObDereferenceObject(Object);
- }
- else if (AdditionalReferences > 1)
- {
- /* Dereference it many times */
- InterlockedExchangeAdd(&ObjectHeader->PointerCount,
- -AdditionalReferences);
}
/* Detach if necessary and fail */
@@ -1670,9 +1671,9 @@
/* Detach */
if (AttachedToProcess) KeUnstackDetachProcess(&ApcState);
- /* Check if this was a user-mode caller with a valid exception port */
+ /* Check if this was a user-mode caller with a valid debug port */
if ((AccessMode != KernelMode) &&
- (PsGetCurrentProcess()->ExceptionPort))
+ (PsGetCurrentProcess()->DebugPort))
{
/* Raise an exception */
Status = KeRaiseUserException(STATUS_INVALID_HANDLE);
@@ -1948,8 +1949,9 @@
BOOLEAN HardErrors;
PAGED_CODE();
- /* Wait for process rundown */
+ /* Wait for process rundown and then complete it */
ExWaitForRundownProtectionRelease(&Process->RundownProtect);
+ ExRundownCompleted(&Process->RundownProtect);
/* Get the object table */
HandleTable = Process->ObjectTable;
@@ -2007,6 +2009,7 @@
AUX_DATA AuxData;
PHANDLE_TABLE HandleTable;
OBJECT_HANDLE_INFORMATION HandleInformation;
+ ULONG AuditMask;
PAGED_CODE();
OBTRACE(OB_HANDLE_DEBUG,
"%s - Duplicating handle: %lx for %p into %p\n",
@@ -2015,6 +2018,9 @@
SourceProcess,
TargetProcess);
+ /* Assume failure */
+ if (TargetHandle) *TargetHandle = NULL;
+
/* Check if we're not duplicating the same access */
if (!(Options & DUPLICATE_SAME_ACCESS))
{
@@ -2029,11 +2035,12 @@
/* Reference the process object */
Status = ObpReferenceProcessObjectByHandle(SourceHandle,
- 0,
+ SourceProcess,
HandleTable,
PreviousMode,
&SourceObject,
- &HandleInformation);
+ &HandleInformation,
+ &AuditMask);
if (!NT_SUCCESS(Status))
{
/* Fail */
@@ -2191,6 +2198,10 @@
/* Now check if incrementing actually failed */
if (!NT_SUCCESS(Status))
{
+ /* Dereference handle tables */
+ ObDereferenceProcessHandleTable(SourceProcess);
+ ObDereferenceProcessHandleTable(TargetProcess);
+
/* Dereference the source object */
ObDereferenceObject(SourceObject);
return Status;
@@ -2283,11 +2294,13 @@
POB_TEMP_BUFFER TempBuffer;
PAGED_CODE();
+ /* Assume failure */
+ *Handle = NULL;
+
/* Check if we didn't get any Object Attributes */
if (!ObjectAttributes)
{
/* Fail with special status code */
- *Handle = NULL;
return STATUS_INVALID_PARAMETER;
}
@@ -2303,7 +2316,12 @@
TRUE,
&TempBuffer->ObjectCreateInfo,
&ObjectName);
- if (!NT_SUCCESS(Status)) return Status;
+ if (!NT_SUCCESS(Status))
+ {
+ /* Fail */
+ ExFreePool(TempBuffer);
+ return Status;
+ }
/* Check if we didn't get an access state */
if (!PassedAccessState)
@@ -2378,6 +2396,9 @@
/* Cleanup after lookup */
ObpCleanupDirectoryLookup(&TempBuffer->LookupContext);
+
+ /* Dereference the object */
+ ObDereferenceObject(Object);
}
else
{
@@ -2466,8 +2487,8 @@
AUX_DATA AuxData;
PAGED_CODE();
- /* Get the Header Info */
- Header = OBJECT_TO_OBJECT_HEADER(Object);
+ /* Assume failure */
+ *Handle = NULL;
/* Reference the object */
Status = ObReferenceObjectByPointer(Object,
@@ -2475,6 +2496,9 @@
ObjectType,
AccessMode);
if (!NT_SUCCESS(Status)) return Status;
+
+ /* Get the Header Info */
+ Header = OBJECT_TO_OBJECT_HEADER(Object);
/* Check if we didn't get an access state */
if (!PassedAccessState)
@@ -2491,6 +2515,20 @@
ObDereferenceObject(Object);
return Status;
}
+ }
+
+ /* Check if we have invalid object attributes */
+ if (Header->Type->TypeInfo.InvalidAttributes & HandleAttributes)
+ {
+ /* Delete the access state */
+ if (PassedAccessState == &AccessState)
+ {
+ SeDeleteAccessState(PassedAccessState);
+ }
+
+ /* Dereference the object */
+ ObDereferenceObject(Object);
+ return STATUS_INVALID_PARAMETER;
}
/* Create the handle */