[12 bug fixes]:

- Isolate FuckedUpCm version of ObpLookupDirectoryObject into CmpLookupDirectoryObject to avoid name info leak.
- Rename ObpIncrementQueryReference to ObpAcquireNameInformation and ObpDecrementQueryReference to ObpReleaseNameInformation and make some changes to make calling a lot easier.
- Fixup reference increment loop in above function.
- Fix incorrect check for defer delete flag instead of query references flag.
- Only clear the directory/directory lock flag in ObpCleanupDirectoryLookup if the directory was actually locked.
- Fix lock logic in ObpLookupDirectoryEntry.
- Properly handle the case when lookup occurs after an existing object, avoid name information leak and reference leak.
- Hold shared lock inside NtQuerydirectoryObject.
- Properly initiailize the directory object in NtCreateDirectoryObject.
- Clear create info before creating the unnamed handle in ObInsertObject.
- Only dereference the target process if we actually have one in NtDuplicateObject.
- Don't double-reference the name information in ObpDeleteNameCheck, thus avoiding another leak.
- Fix object case sensitivity check in ObpLookupObjectName.

svn path=/trunk/; revision=25469
This commit is contained in:
Alex Ionescu 2007-01-15 20:24:40 +00:00
parent 4e9c7cf7e4
commit d591f751c7
5 changed files with 277 additions and 161 deletions

View file

@ -27,6 +27,121 @@ CmiGetLinkTarget(PEREGISTRY_HIVE RegistryHive,
PUNICODE_STRING TargetPath); PUNICODE_STRING TargetPath);
/* FUNCTONS *****************************************************************/ /* FUNCTONS *****************************************************************/
PVOID
NTAPI
CmpLookupEntryDirectory(IN POBJECT_DIRECTORY Directory,
IN PUNICODE_STRING Name,
IN ULONG Attributes,
IN UCHAR SearchShadow,
IN POBP_LOOKUP_CONTEXT Context)
{
BOOLEAN CaseInsensitive = FALSE;
POBJECT_HEADER_NAME_INFO HeaderNameInfo;
ULONG HashValue;
ULONG HashIndex;
LONG TotalChars;
WCHAR CurrentChar;
POBJECT_DIRECTORY_ENTRY *AllocatedEntry;
POBJECT_DIRECTORY_ENTRY *LookupBucket;
POBJECT_DIRECTORY_ENTRY CurrentEntry;
PVOID FoundObject = NULL;
PWSTR Buffer;
PAGED_CODE();
/* Always disable this until we have DOS Device Maps */
SearchShadow = FALSE;
/* Fail if we don't have a directory or name */
if (!(Directory) || !(Name)) goto Quickie;
/* Get name information */
TotalChars = Name->Length / sizeof(WCHAR);
Buffer = Name->Buffer;
/* Fail if the name is empty */
if (!(Buffer) || !(TotalChars)) goto Quickie;
/* Set up case-sensitivity */
if (Attributes & OBJ_CASE_INSENSITIVE) CaseInsensitive = TRUE;
/* Create the Hash */
for (HashValue = 0; TotalChars; TotalChars--)
{
/* Go to the next Character */
CurrentChar = *Buffer++;
/* Prepare the Hash */
HashValue += (HashValue << 1) + (HashValue >> 1);
/* Create the rest based on the name */
if (CurrentChar < 'a') HashValue += CurrentChar;
else if (CurrentChar > 'z') HashValue += RtlUpcaseUnicodeChar(CurrentChar);
else HashValue += (CurrentChar - ('a'-'A'));
}
/* Merge it with our number of hash buckets */
HashIndex = HashValue % 37;
/* Save the result */
Context->HashValue = HashValue;
Context->HashIndex = (USHORT)HashIndex;
/* Get the root entry and set it as our lookup bucket */
AllocatedEntry = &Directory->HashBuckets[HashIndex];
LookupBucket = AllocatedEntry;
/* Start looping */
while ((CurrentEntry = *AllocatedEntry))
{
/* Do the hashes match? */
if (CurrentEntry->HashValue == HashValue)
{
/* Make sure that it has a name */
ASSERT(OBJECT_TO_OBJECT_HEADER(CurrentEntry->Object)->NameInfoOffset != 0);
/* Get the name information */
HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(OBJECT_TO_OBJECT_HEADER(CurrentEntry->Object));
/* Do the names match? */
if ((Name->Length == HeaderNameInfo->Name.Length) &&
(RtlEqualUnicodeString(Name, &HeaderNameInfo->Name, CaseInsensitive)))
{
break;
}
}
/* Move to the next entry */
AllocatedEntry = &CurrentEntry->ChainLink;
}
/* Check if we still have an entry */
if (CurrentEntry)
{
/* Set this entry as the first, to speed up incoming insertion */
if (AllocatedEntry != LookupBucket)
{
/* Set the Current Entry */
*AllocatedEntry = CurrentEntry->ChainLink;
/* Link to the old Hash Entry */
CurrentEntry->ChainLink = *LookupBucket;
/* Set the new Hash Entry */
*LookupBucket = CurrentEntry;
}
/* Save the found object */
FoundObject = CurrentEntry->Object;
if (!FoundObject) goto Quickie;
}
Quickie:
/* Return the object we found */
Context->Object = FoundObject;
return FoundObject;
}
NTSTATUS NTSTATUS
NTAPI NTAPI
CmFindObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo, CmFindObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
@ -137,9 +252,10 @@ CmFindObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
if (End != NULL) *End = 0; if (End != NULL) *End = 0;
RtlInitUnicodeString(&StartUs, Start); RtlInitUnicodeString(&StartUs, Start);
ObpInitializeDirectoryLookup(&Context);
Context.DirectoryLocked = TRUE; Context.DirectoryLocked = TRUE;
Context.Directory = CurrentObject; Context.Directory = CurrentObject;
FoundObject = ObpLookupEntryDirectory(CurrentObject, &StartUs, Attributes, FALSE, &Context); FoundObject = CmpLookupEntryDirectory(CurrentObject, &StartUs, Attributes, FALSE, &Context);
if (FoundObject == NULL) if (FoundObject == NULL)
{ {
if (End != NULL) if (End != NULL)

View file

@ -15,48 +15,58 @@
#define OBP_LOCK_STATE_RELEASED 0xEEEE1234 #define OBP_LOCK_STATE_RELEASED 0xEEEE1234
#define OBP_LOCK_STATE_INITIALIZED 0xFFFF1234 #define OBP_LOCK_STATE_INITIALIZED 0xFFFF1234
ULONG POBJECT_HEADER_NAME_INFO
FORCEINLINE FORCEINLINE
ObpIncrementQueryReference(IN POBJECT_HEADER ObjectHeader, ObpAcquireNameInformation(IN POBJECT_HEADER ObjectHeader)
IN POBJECT_HEADER_NAME_INFO ObjectNameInfo)
{ {
POBJECT_HEADER_NAME_INFO ObjectNameInfo;
ULONG NewValue, References; ULONG NewValue, References;
/* Get the number of references */ /* Make sure we have name information at all */
NewValue = ObjectNameInfo->QueryReferences; ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
while ((NewValue != 0) && (References = NewValue)) if (!ObjectNameInfo) return NULL;
{
/* Increment the number of references */
if (InterlockedCompareExchange((PLONG)&ObjectNameInfo->QueryReferences,
NewValue + 1,
NewValue) == References)
{
/* Check if the object is to be deferred deleted */
if (ObjectHeader->Flags & OB_FLAG_DEFER_DELETE)
{
/* FIXME: Unhandled*/
DbgPrint("OB: Unhandled path\n");
KEBUGCHECK(0);
}
/* Done looping */ /* Get the number of references */
NewValue = ObjectNameInfo->QueryReferences; References = ObjectNameInfo->QueryReferences;
break; for (;;)
} {
/* Check if the count is 0 and fail if so */
if (!References) return NULL;
/* Increment the number of references */
NewValue = InterlockedCompareExchange((PLONG)&ObjectNameInfo->
QueryReferences,
References + 1,
References);
if (NewValue == References) break;
/* We failed, try again */
References = NewValue;
} }
/* Return the number of references */ /* Check for magic flag */
return NewValue; if (ObjectNameInfo->QueryReferences & 0x80000000)
{
/* FIXME: Unhandled*/
DbgPrint("OB: Unhandled path\n");
KEBUGCHECK(0);
}
/* Return the name information */
return ObjectNameInfo;
} }
VOID VOID
FORCEINLINE FORCEINLINE
ObpDecrementQueryReference(IN POBJECT_HEADER_NAME_INFO HeaderNameInfo) ObpReleaseNameInformation(IN POBJECT_HEADER_NAME_INFO HeaderNameInfo)
{ {
POBJECT_DIRECTORY Directory; POBJECT_DIRECTORY Directory;
/* Bail out if there's no info at all */
if (!HeaderNameInfo) return;
/* Remove a query reference and check if it was the last one */ /* Remove a query reference and check if it was the last one */
if (!InterlockedExchangeAdd((PLONG)&HeaderNameInfo->QueryReferences, -1)) if (!InterlockedDecrement((PLONG)&HeaderNameInfo->QueryReferences))
{ {
/* Check if we have a name */ /* Check if we have a name */
if (HeaderNameInfo->Name.Buffer) if (HeaderNameInfo->Name.Buffer)
@ -149,8 +159,8 @@ ObpReleaseLookupContextObject(IN POBP_LOOKUP_CONTEXT Context)
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Context->Object); ObjectHeader = OBJECT_TO_OBJECT_HEADER(Context->Object);
HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader); HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
/* Check if we do have name information */ /* release the name information */
if (HeaderNameInfo) ObpDecrementQueryReference(HeaderNameInfo); ObpReleaseNameInformation(HeaderNameInfo);
/* Dereference the object */ /* Dereference the object */
ObDereferenceObject(Context->Object); ObDereferenceObject(Context->Object);
@ -167,11 +177,11 @@ ObpCleanupDirectoryLookup(IN POBP_LOOKUP_CONTEXT Context)
{ {
/* Release the lock */ /* Release the lock */
ObpReleaseDirectoryLock(Context->Directory, Context); ObpReleaseDirectoryLock(Context->Directory, Context);
Context->Directory = NULL;
Context->DirectoryLocked = FALSE;
} }
/* Clear the context */ /* Clear the context */
Context->Directory = NULL;
Context->DirectoryLocked = FALSE;
ObpReleaseLookupContextObject(Context); ObpReleaseLookupContextObject(Context);
} }

View file

@ -220,45 +220,24 @@ ObpLookupEntryDirectory(IN POBJECT_DIRECTORY Directory,
/* Set this entry as the first, to speed up incoming insertion */ /* Set this entry as the first, to speed up incoming insertion */
if (AllocatedEntry != LookupBucket) if (AllocatedEntry != LookupBucket)
{ {
/* Check if the directory was locked */ /* Check if the directory was locked or convert the lock */
if (!Context->DirectoryLocked) if ((Context->DirectoryLocked) ||
(ExConvertPushLockSharedToExclusive(&Directory->Lock)))
{ {
/* Convert the lock from shared to exclusive */ /* Set the Current Entry */
ExConvertPushLockSharedToExclusive(&Directory->Lock); *AllocatedEntry = CurrentEntry->ChainLink;
/* Link to the old Hash Entry */
CurrentEntry->ChainLink = *LookupBucket;
/* Set the new Hash Entry */
*LookupBucket = CurrentEntry;
} }
/* Set the Current Entry */
*AllocatedEntry = CurrentEntry->ChainLink;
/* Link to the old Hash Entry */
CurrentEntry->ChainLink = *LookupBucket;
/* Set the new Hash Entry */
*LookupBucket = CurrentEntry;
} }
/* Save the found object */ /* Save the found object */
FoundObject = CurrentEntry->Object; FoundObject = CurrentEntry->Object;
if (!FoundObject) goto Quickie; goto Quickie;
/* Get the object name information */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(FoundObject);
HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
if (HeaderNameInfo)
{
/* Add a query reference */
ObpIncrementQueryReference(ObjectHeader, HeaderNameInfo);
}
/* Reference the object being looked up */
ObReferenceObject(FoundObject);
/* Check if the directory was locked */
if (!Context->DirectoryLocked)
{
/* Release the lock */
ObpReleaseDirectoryLock(Directory, Context);
}
} }
else else
{ {
@ -278,11 +257,34 @@ ObpLookupEntryDirectory(IN POBJECT_DIRECTORY Directory,
} }
Quickie: Quickie:
/* Check if we inserted an object */
if (FoundObject)
{
/* Get the object name information */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(FoundObject);
ObpAcquireNameInformation(ObjectHeader);
/* Reference the object being looked up */
ObReferenceObject(FoundObject);
/* Check if the directory was locked */
if (!Context->DirectoryLocked)
{
/* Release the lock */
ObpReleaseDirectoryLock(Directory, Context);
}
}
/* Check if we found an object already */ /* Check if we found an object already */
if (Context->Object) if (Context->Object)
{ {
/* We already did a lookup, so remove this object's query reference */ /* We already did a lookup, so remove this object's query reference */
//ObpDecrementQueryReference(Context->Object); ObjectHeader = OBJECT_TO_OBJECT_HEADER(Context->Object);
HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
ObpReleaseNameInformation(HeaderNameInfo);
/* Also dereference the object itself */
ObDereferenceObject(Context->Object);
} }
/* Return the object we found */ /* Return the object we found */
@ -354,17 +356,17 @@ ObpDeleteEntryDirectory(POBP_LOOKUP_CONTEXT Context)
*--*/ *--*/
NTSTATUS NTSTATUS
NTAPI NTAPI
NtOpenDirectoryObject (OUT PHANDLE DirectoryHandle, NtOpenDirectoryObject(OUT PHANDLE DirectoryHandle,
IN ACCESS_MASK DesiredAccess, IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes) IN POBJECT_ATTRIBUTES ObjectAttributes)
{ {
HANDLE hDirectory; HANDLE Directory;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE(); PAGED_CODE();
/* Check if we need to do any probing */ /* Check if we need to do any probing */
if(PreviousMode != KernelMode) if (PreviousMode != KernelMode)
{ {
_SEH_TRY _SEH_TRY
{ {
@ -377,8 +379,6 @@ NtOpenDirectoryObject (OUT PHANDLE DirectoryHandle,
Status = _SEH_GetExceptionCode(); Status = _SEH_GetExceptionCode();
} }
_SEH_END; _SEH_END;
/* If we failed, return the error */
if(!NT_SUCCESS(Status)) return Status; if(!NT_SUCCESS(Status)) return Status;
} }
@ -389,13 +389,13 @@ NtOpenDirectoryObject (OUT PHANDLE DirectoryHandle,
NULL, NULL,
DesiredAccess, DesiredAccess,
NULL, NULL,
&hDirectory); &Directory);
if(NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
_SEH_TRY _SEH_TRY
{ {
/* Write back the handle to the caller */ /* Write back the handle to the caller */
*DirectoryHandle = hDirectory; *DirectoryHandle = Directory;
} }
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter) _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
{ {
@ -476,10 +476,14 @@ NtQueryDirectoryObject(IN HANDLE DirectoryHandle,
POBJECT_HEADER_NAME_INFO ObjectNameInfo; POBJECT_HEADER_NAME_INFO ObjectNameInfo;
UNICODE_STRING Name; UNICODE_STRING Name;
PWSTR p; PWSTR p;
OBP_LOOKUP_CONTEXT LookupContext;
PAGED_CODE(); PAGED_CODE();
/* Initialize lookup */
ObpInitializeDirectoryLookup(&LookupContext);
/* Check if we need to do any probing */ /* Check if we need to do any probing */
if(PreviousMode != KernelMode) if (PreviousMode != KernelMode)
{ {
_SEH_TRY _SEH_TRY
{ {
@ -491,7 +495,7 @@ NtQueryDirectoryObject(IN HANDLE DirectoryHandle,
if (!RestartScan) SkipEntries = *Context; if (!RestartScan) SkipEntries = *Context;
/* Probe the return length if the caller specified one */ /* Probe the return length if the caller specified one */
if(ReturnLength) ProbeForWriteUlong(ReturnLength); if (ReturnLength) ProbeForWriteUlong(ReturnLength);
} }
_SEH_HANDLE _SEH_HANDLE
{ {
@ -499,8 +503,6 @@ NtQueryDirectoryObject(IN HANDLE DirectoryHandle,
Status = _SEH_GetExceptionCode(); Status = _SEH_GetExceptionCode();
} }
_SEH_END; _SEH_END;
/* Return the exception to caller if we failed */
if(!NT_SUCCESS(Status)) return Status; if(!NT_SUCCESS(Status)) return Status;
} }
else if (!RestartScan) else if (!RestartScan)
@ -531,6 +533,9 @@ NtQueryDirectoryObject(IN HANDLE DirectoryHandle,
return Status; return Status;
} }
/* Lock directory in shared mode */
ObpAcquireDirectoryLockShared(Directory, &LookupContext);
/* Start at position 0 */ /* Start at position 0 */
DirectoryInfo = (POBJECT_DIRECTORY_INFORMATION)LocalBuffer; DirectoryInfo = (POBJECT_DIRECTORY_INFORMATION)LocalBuffer;
TotalLength = sizeof(OBJECT_DIRECTORY_INFORMATION); TotalLength = sizeof(OBJECT_DIRECTORY_INFORMATION);
@ -691,6 +696,9 @@ Quickie:
} }
_SEH_END; _SEH_END;
/* Unlock the directory */
ObpReleaseDirectoryLock(Directory, &LookupContext);
/* Dereference the directory and free our buffer */ /* Dereference the directory and free our buffer */
ObDereferenceObject(Directory); ObDereferenceObject(Directory);
ExFreePool(LocalBuffer); ExFreePool(LocalBuffer);
@ -726,7 +734,7 @@ NtCreateDirectoryObject(OUT PHANDLE DirectoryHandle,
IN POBJECT_ATTRIBUTES ObjectAttributes) IN POBJECT_ATTRIBUTES ObjectAttributes)
{ {
POBJECT_DIRECTORY Directory; POBJECT_DIRECTORY Directory;
HANDLE hDirectory; HANDLE NewHandle;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE(); PAGED_CODE();
@ -745,8 +753,6 @@ NtCreateDirectoryObject(OUT PHANDLE DirectoryHandle,
Status = _SEH_GetExceptionCode(); Status = _SEH_GetExceptionCode();
} }
_SEH_END; _SEH_END;
/* If we failed, return the error */
if(!NT_SUCCESS(Status)) return Status; if(!NT_SUCCESS(Status)) return Status;
} }
@ -760,30 +766,33 @@ NtCreateDirectoryObject(OUT PHANDLE DirectoryHandle,
0, 0,
0, 0,
(PVOID*)&Directory); (PVOID*)&Directory);
if(NT_SUCCESS(Status)) if (!NT_SUCCESS(Status)) return Status;
/* Setup the object */
RtlZeroMemory(Directory, sizeof(OBJECT_DIRECTORY));
ExInitializePushLock((PULONG_PTR)&Directory->Lock);
Directory->SessionId = -1;
/* Insert it into the handle table */
Status = ObInsertObject((PVOID)Directory,
NULL,
DesiredAccess,
0,
NULL,
&NewHandle);
/* Enter SEH to protect write */
_SEH_TRY
{ {
/* Insert it into the handle table */ /* Return the handle back to the caller */
Status = ObInsertObject((PVOID)Directory, *DirectoryHandle = NewHandle;
NULL,
DesiredAccess,
0,
NULL,
&hDirectory);
if(NT_SUCCESS(Status))
{
_SEH_TRY
{
/* Return the handle back to the caller */
*DirectoryHandle = hDirectory;
}
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
{
/* Get the exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
} }
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
{
/* Get the exception code */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
/* Return status to caller */ /* Return status to caller */
return Status; return Status;

View file

@ -2693,7 +2693,6 @@ ObInsertObject(IN PVOID Object,
{ {
/* Display warning and break into debugger */ /* Display warning and break into debugger */
DPRINT1("OB: Attempting to insert existing object %08x\n", Object); DPRINT1("OB: Attempting to insert existing object %08x\n", Object);
KEBUGCHECK(0);
DbgBreakPoint(); DbgBreakPoint();
/* Allow debugger to continue */ /* Allow debugger to continue */
@ -2703,22 +2702,11 @@ ObInsertObject(IN PVOID Object,
/* Get the create and name info, as well as the object type */ /* Get the create and name info, as well as the object type */
ObjectCreateInfo = ObjectHeader->ObjectCreateInfo; ObjectCreateInfo = ObjectHeader->ObjectCreateInfo;
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader); ObjectNameInfo = ObpAcquireNameInformation(ObjectHeader);
ObjectType = ObjectHeader->Type; ObjectType = ObjectHeader->Type;
ObjectName = NULL;
/* Check if we have name information */
if (ObjectNameInfo)
{
/* Add a query reference */
if (!ObpIncrementQueryReference(ObjectHeader, ObjectNameInfo))
{
/* There are no query references, so the name info is invalid */
ObjectNameInfo = NULL;
}
}
/* Check if this is an named object */ /* Check if this is an named object */
ObjectName = NULL;
if ((ObjectNameInfo) && (ObjectNameInfo->Name.Buffer)) if ((ObjectNameInfo) && (ObjectNameInfo->Name.Buffer))
{ {
/* Get the object name */ /* Get the object name */
@ -2738,6 +2726,7 @@ ObInsertObject(IN PVOID Object,
{ {
/* Assume failure */ /* Assume failure */
*Handle = NULL; *Handle = NULL;
ObjectHeader->ObjectCreateInfo = NULL;
/* Create the handle */ /* Create the handle */
Status = ObpCreateUnnamedHandle(Object, Status = ObpCreateUnnamedHandle(Object,
@ -2750,10 +2739,9 @@ ObInsertObject(IN PVOID Object,
/* Free the create information */ /* Free the create information */
ObpFreeAndReleaseCapturedAttributes(ObjectCreateInfo); ObpFreeAndReleaseCapturedAttributes(ObjectCreateInfo);
ObjectHeader->ObjectCreateInfo = NULL;
/* Remove a query reference if we added one */ /* Release the object name information */
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo); ObpReleaseNameInformation(ObjectNameInfo);
/* Remove the extra keep-alive reference */ /* Remove the extra keep-alive reference */
ObDereferenceObject(Object); ObDereferenceObject(Object);
@ -2779,7 +2767,7 @@ ObInsertObject(IN PVOID Object,
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
/* Fail */ /* Fail */
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo); ObpReleaseNameInformation(ObjectNameInfo);
ObDereferenceObject(Object); ObDereferenceObject(Object);
return Status; return Status;
} }
@ -2793,7 +2781,7 @@ ObInsertObject(IN PVOID Object,
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
/* Fail */ /* Fail */
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo); ObpReleaseNameInformation(ObjectNameInfo);
ObDereferenceObject(Object); ObDereferenceObject(Object);
return Status; return Status;
} }
@ -2855,7 +2843,7 @@ ObInsertObject(IN PVOID Object,
ObpCleanupDirectoryLookup(&Context); ObpCleanupDirectoryLookup(&Context);
/* Remove query reference that we added */ /* Remove query reference that we added */
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo); ObpReleaseNameInformation(ObjectNameInfo);
/* Dereference the object and delete the access state */ /* Dereference the object and delete the access state */
ObDereferenceObject(Object); ObDereferenceObject(Object);
@ -2922,11 +2910,19 @@ ObInsertObject(IN PVOID Object,
/* Check if anything until now failed */ /* Check if anything until now failed */
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
/* Cleanup lookup context */ /* Check if the directory was added */
if (Context.DirectoryLocked)
{
/* Weird case where we need to do a manual delete */
DPRINT1("Unhandled path\n");
KEBUGCHECK(0);
}
/* Cleanup the lookup */
ObpCleanupDirectoryLookup(&Context); ObpCleanupDirectoryLookup(&Context);
/* Remove query reference that we added */ /* Remove query reference that we added */
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo); ObpReleaseNameInformation(ObjectNameInfo);
/* Dereference the object and delete the access state */ /* Dereference the object and delete the access state */
ObDereferenceObject(Object); ObDereferenceObject(Object);
@ -2971,7 +2967,7 @@ ObInsertObject(IN PVOID Object,
} }
/* Remove a query reference */ /* Remove a query reference */
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo); ObpReleaseNameInformation(ObjectNameInfo);
/* Remove the extra keep-alive reference */ /* Remove the extra keep-alive reference */
ObDereferenceObject(Object); ObDereferenceObject(Object);
@ -3078,7 +3074,8 @@ NtDuplicateObject(IN HANDLE SourceProcessHandle,
SourceProcessHandle, SourceProcessHandle,
TargetProcessHandle); TargetProcessHandle);
if((TargetHandle) && (PreviousMode != KernelMode)) /* Check if we have a target handle */
if ((TargetHandle) && (PreviousMode != KernelMode))
{ {
/* Enter SEH */ /* Enter SEH */
_SEH_TRY _SEH_TRY
@ -3092,8 +3089,6 @@ NtDuplicateObject(IN HANDLE SourceProcessHandle,
Status = _SEH_GetExceptionCode(); Status = _SEH_GetExceptionCode();
} }
_SEH_END; _SEH_END;
/* Fail if the pointer was invalid */
if (!NT_SUCCESS(Status)) return Status; if (!NT_SUCCESS(Status)) return Status;
} }
@ -3168,7 +3163,7 @@ NtDuplicateObject(IN HANDLE SourceProcessHandle,
hTarget, hTarget,
TargetProcessHandle, TargetProcessHandle,
Status); Status);
ObDereferenceObject(Target); if (Target) ObDereferenceObject(Target);
ObDereferenceObject(SourceProcess); ObDereferenceObject(SourceProcess);
return Status; return Status;
} }

View file

@ -170,20 +170,9 @@ ObpDeleteNameCheck(IN PVOID Object)
/* Get object structures */ /* Get object structures */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader); ObjectNameInfo = ObpAcquireNameInformation(ObjectHeader);
ObjectType = ObjectHeader->Type; ObjectType = ObjectHeader->Type;
/* Check if we have a name information structure */
if (ObjectNameInfo)
{
/* Add a query reference */
if (!ObpIncrementQueryReference(ObjectHeader, ObjectNameInfo))
{
/* No references, so the name info is invalid */
ObjectNameInfo = NULL;
}
}
/* /*
* Check if the handle count is 0, if the object is named, * Check if the handle count is 0, if the object is named,
* and if the object isn't a permanent object. * and if the object isn't a permanent object.
@ -225,21 +214,14 @@ ObpDeleteNameCheck(IN PVOID Object)
ObpDeleteSymbolicLinkName(Object); ObpDeleteSymbolicLinkName(Object);
} }
/* Add a query reference */
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
if (!ObpIncrementQueryReference(ObjectHeader, ObjectNameInfo))
{
/* No references, so the name info is invalid */
ObjectNameInfo = NULL;
}
/* Check if the magic protection flag is set */ /* Check if the magic protection flag is set */
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
if ((ObjectNameInfo) && if ((ObjectNameInfo) &&
(ObjectNameInfo->QueryReferences & 0x40000000)) (ObjectNameInfo->QueryReferences & 0x40000000))
{ {
/* Add deletion flag */ /* Remove protection flag */
InterlockedExchangeAdd((PLONG)&ObjectNameInfo->QueryReferences, InterlockedExchangeAdd((PLONG)&ObjectNameInfo->QueryReferences,
0xC0000000); -0x40000000);
} }
/* Get the directory */ /* Get the directory */
@ -254,13 +236,13 @@ ObpDeleteNameCheck(IN PVOID Object)
ObpCleanupDirectoryLookup(&Context); ObpCleanupDirectoryLookup(&Context);
/* Remove another query reference since we added one on top */ /* Remove another query reference since we added one on top */
ObpDecrementQueryReference(ObjectNameInfo); ObpReleaseNameInformation(ObjectNameInfo);
/* Check if we were inserted in a directory */ /* Check if we were inserted in a directory */
if (Directory) if (Directory)
{ {
/* We were, so first remove the extra reference we had added */ /* We were, so first remove the extra reference we had added */
ObpDecrementQueryReference(ObjectNameInfo); ObpReleaseNameInformation(ObjectNameInfo);
/* Now dereference the object as well */ /* Now dereference the object as well */
ObDereferenceObject(Object); ObDereferenceObject(Object);
@ -269,7 +251,7 @@ ObpDeleteNameCheck(IN PVOID Object)
else else
{ {
/* Remove the reference we added */ /* Remove the reference we added */
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo); ObpReleaseNameInformation(ObjectNameInfo);
} }
} }
@ -313,11 +295,15 @@ ObpLookupObjectName(IN HANDLE RootHandle,
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
Object = NULL; Object = NULL;
/* Check if case-insensitivity is forced */ /* Check if case-insensitivity is checked */
if ((ObpCaseInsensitive) || (ObjectType->TypeInfo.CaseInsensitive)) if (ObpCaseInsensitive)
{ {
/* Add the flag to disable case sensitivity */ /* Check if the object type requests this */
Attributes |= OBJ_CASE_INSENSITIVE; if (!(ObjectType) || (ObjectType->TypeInfo.CaseInsensitive))
{
/* Add the flag to disable case sensitivity */
Attributes |= OBJ_CASE_INSENSITIVE;
}
} }
/* Check if this is a access checks are being forced */ /* Check if this is a access checks are being forced */