- Fix a bug in ExfWakePushLock.

- Implement object directory locking to avoid race conditions in Ob and enable most of the query referencing code.

svn path=/trunk/; revision=25407
This commit is contained in:
Alex Ionescu 2007-01-10 01:00:46 +00:00
parent 8fb22da8e5
commit 6e3ccb6ffd
8 changed files with 41 additions and 94 deletions

View file

@ -97,7 +97,7 @@ ExfWakePushLock(PEX_PUSH_LOCK PushLock,
OldValue = NewValue; OldValue = NewValue;
/* Check if it's still locked */ /* Check if it's still locked */
if (OldValue.Locked) continue; if (!OldValue.Locked) break;
} }
} }

View file

@ -51,7 +51,7 @@ ObpIncrementQueryReference(IN POBJECT_HEADER ObjectHeader,
VOID VOID
FORCEINLINE FORCEINLINE
_ObpDecrementQueryReference(IN POBJECT_HEADER_NAME_INFO HeaderNameInfo) ObpDecrementQueryReference(IN POBJECT_HEADER_NAME_INFO HeaderNameInfo)
{ {
POBJECT_DIRECTORY Directory; POBJECT_DIRECTORY Directory;
@ -79,7 +79,7 @@ _ObpDecrementQueryReference(IN POBJECT_HEADER_NAME_INFO HeaderNameInfo)
VOID VOID
FORCEINLINE FORCEINLINE
_ObpAcquireDirectoryLockShared(IN POBJECT_DIRECTORY Directory, ObpAcquireDirectoryLockShared(IN POBJECT_DIRECTORY Directory,
IN POBP_LOOKUP_CONTEXT Context) IN POBP_LOOKUP_CONTEXT Context)
{ {
/* It's not, set lock flag */ /* It's not, set lock flag */
@ -95,7 +95,7 @@ _ObpAcquireDirectoryLockShared(IN POBJECT_DIRECTORY Directory,
VOID VOID
FORCEINLINE FORCEINLINE
_ObpAcquireDirectoryLockExclusive(IN POBJECT_DIRECTORY Directory, ObpAcquireDirectoryLockExclusive(IN POBJECT_DIRECTORY Directory,
IN POBP_LOOKUP_CONTEXT Context) IN POBP_LOOKUP_CONTEXT Context)
{ {
/* Update lock flag */ /* Update lock flag */
@ -115,7 +115,7 @@ _ObpAcquireDirectoryLockExclusive(IN POBJECT_DIRECTORY Directory,
VOID VOID
FORCEINLINE FORCEINLINE
_ObpReleaseDirectoryLock(IN POBJECT_DIRECTORY Directory, ObpReleaseDirectoryLock(IN POBJECT_DIRECTORY Directory,
IN POBP_LOOKUP_CONTEXT Context) IN POBP_LOOKUP_CONTEXT Context)
{ {
/* Release the lock */ /* Release the lock */
@ -126,7 +126,7 @@ _ObpReleaseDirectoryLock(IN POBJECT_DIRECTORY Directory,
VOID VOID
FORCEINLINE FORCEINLINE
_ObpInitializeDirectoryLookup(IN POBP_LOOKUP_CONTEXT Context) ObpInitializeDirectoryLookup(IN POBP_LOOKUP_CONTEXT Context)
{ {
/* Initialize a null context */ /* Initialize a null context */
Context->Object = NULL; Context->Object = NULL;
@ -137,7 +137,7 @@ _ObpInitializeDirectoryLookup(IN POBP_LOOKUP_CONTEXT Context)
VOID VOID
FORCEINLINE FORCEINLINE
_ObpReleaseLookupContextObject(IN POBP_LOOKUP_CONTEXT Context) ObpReleaseLookupContextObject(IN POBP_LOOKUP_CONTEXT Context)
{ {
POBJECT_HEADER ObjectHeader; POBJECT_HEADER ObjectHeader;
POBJECT_HEADER_NAME_INFO HeaderNameInfo; POBJECT_HEADER_NAME_INFO HeaderNameInfo;
@ -150,7 +150,7 @@ _ObpReleaseLookupContextObject(IN POBP_LOOKUP_CONTEXT Context)
HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader); HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
/* Check if we do have name information */ /* Check if we do have name information */
if (HeaderNameInfo) _ObpDecrementQueryReference(HeaderNameInfo); if (HeaderNameInfo) ObpDecrementQueryReference(HeaderNameInfo);
/* Dereference the object */ /* Dereference the object */
ObDereferenceObject(Context->Object); ObDereferenceObject(Context->Object);
@ -160,61 +160,21 @@ _ObpReleaseLookupContextObject(IN POBP_LOOKUP_CONTEXT Context)
VOID VOID
FORCEINLINE FORCEINLINE
_ObpCleanupDirectoryLookup(IN POBP_LOOKUP_CONTEXT Context) ObpCleanupDirectoryLookup(IN POBP_LOOKUP_CONTEXT Context)
{ {
/* Check if we came back with the directory locked */ /* Check if we came back with the directory locked */
if (Context->DirectoryLocked) if (Context->DirectoryLocked)
{ {
/* Release the lock */ /* Release the lock */
_ObpReleaseDirectoryLock(Context->Directory, Context); ObpReleaseDirectoryLock(Context->Directory, Context);
} }
/* Clear the context */ /* Clear the context */
Context->Directory = NULL; Context->Directory = NULL;
Context->DirectoryLocked = FALSE; Context->DirectoryLocked = FALSE;
_ObpReleaseLookupContextObject(Context); ObpReleaseLookupContextObject(Context);
} }
#if _OB_DEBUG_
#define ObpAcquireDirectoryLockShared(a, b) \
{ \
DbgPrint("OB QUERY: Acquiring lock at %s %d\n", __FUNCTION__, __LINE__);\
_ObpAcquireDirectoryLockShared(a, b); \
}
#define ObpAcquireDirectoryLockExclusive(a, b) \
{ \
DbgPrint("OB QUERY: Acquiring lock at %s %d\n", __FUNCTION__, __LINE__);\
_ObpAcquireDirectoryLockExclusive(a, b); \
}
#define ObpReleaseDirectoryLock(a, b) \
{ \
DbgPrint("OB QUERY: Releasing lock at %s %d\n", __FUNCTION__, __LINE__);\
_ObpReleaseDirectoryLock(a, b); \
}
#define ObpInitializeDirectoryLookup(a) \
{ \
DbgPrint("OB QUERY: Initialization at %s %d\n", __FUNCTION__, __LINE__);\
_ObpInitializeDirectoryLookup(a); \
}
#define ObpCleanupDirectoryLookup(a, b) \
{ \
DbgPrint("OB QUERY: Cleanup at %s %d\n", __FUNCTION__, __LINE__); \
_ObpCleanupDirectoryLookup(a, b); \
}
#define ObpDecrementQueryReference(a) \
{ \
DbgPrint("OB QUERY: Decrement at %s %d\n", __FUNCTION__, __LINE__); \
_ObpDecrementQueryReference(a); \
}
#else
#define ObpDecrementQueryReference _ObpDecrementQueryReference
#define ObpAcquireDirectoryLockExclusive _ObpAcquireDirectoryLockExclusive
#define ObpAcquireDirectoryLockShared _ObpAcquireDirectoryLockShared
#define ObpReleaseDirectoryLock _ObpReleaseDirectoryLock
#define ObpInitializeDirectoryLookup _ObpInitializeDirectoryLookup
#define ObpCleanupDirectoryLookup _ObpCleanupDirectoryLookup
#endif
VOID VOID
FORCEINLINE FORCEINLINE
ObpEnterObjectTypeMutex(IN POBJECT_TYPE ObjectType) ObpEnterObjectTypeMutex(IN POBJECT_TYPE ObjectType)

View file

@ -247,11 +247,11 @@ ObpLookupEntryDirectory(IN POBJECT_DIRECTORY Directory,
if (HeaderNameInfo) if (HeaderNameInfo)
{ {
/* Add a query reference */ /* Add a query reference */
//ObpIncrementQueryReference(ObjectHeader, HeaderNameInfo); ObpIncrementQueryReference(ObjectHeader, HeaderNameInfo);
} }
/* Reference the object being looked up */ /* Reference the object being looked up */
//ObReferenceObject(FoundObject); ObReferenceObject(FoundObject);
/* Check if the directory was locked */ /* Check if the directory was locked */
if (!Context->DirectoryLocked) if (!Context->DirectoryLocked)
@ -282,7 +282,7 @@ Quickie:
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 */
//ObpRemoveQueryReference(Context->Object); //ObpDecrementQueryReference(Context->Object);
} }
/* Return the object we found */ /* Return the object we found */

View file

@ -1249,7 +1249,7 @@ ObpCreateHandle(IN OB_OPEN_REASON OpenReason,
if ((Type) && (ObjectType != Type)) if ((Type) && (ObjectType != Type))
{ {
/* They don't, cleanup */ /* They don't, cleanup */
//if (Context) ObpCleanupDirectoryLookup(Context); if (Context) ObpCleanupDirectoryLookup(Context);
return STATUS_OBJECT_TYPE_MISMATCH; return STATUS_OBJECT_TYPE_MISMATCH;
} }
@ -1287,7 +1287,7 @@ ObpCreateHandle(IN OB_OPEN_REASON OpenReason,
* We failed (meaning security failure, according to NT Internals) * We failed (meaning security failure, according to NT Internals)
* detach and return * detach and return
*/ */
//if (Context) ObpCleanupDirectoryLookup(Context); if (Context) ObpCleanupDirectoryLookup(Context);
if (AttachedToProcess) KeUnstackDetachProcess(&ApcState); if (AttachedToProcess) KeUnstackDetachProcess(&ApcState);
return Status; return Status;
} }
@ -1327,8 +1327,7 @@ ObpCreateHandle(IN OB_OPEN_REASON OpenReason,
} }
/* Now we can release the object */ /* Now we can release the object */
//if (Context) ObpCleanupDirectoryLookup(Context); if (Context) ObpCleanupDirectoryLookup(Context);
if (Context) Context->Object = NULL;
/* Save the object header */ /* Save the object header */
NewEntry.Object = ObjectHeader; NewEntry.Object = ObjectHeader;
@ -2117,8 +2116,7 @@ ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
/* Cleanup after lookup */ /* Cleanup after lookup */
//ObpCleanupDirectoryLookup(&TempBuffer->LookupContext); ObpCleanupDirectoryLookup(&TempBuffer->LookupContext);
TempBuffer->LookupContext.Object = NULL;
goto Cleanup; goto Cleanup;
} }
@ -2152,8 +2150,7 @@ ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,
Status = STATUS_INVALID_PARAMETER; Status = STATUS_INVALID_PARAMETER;
/* Cleanup after lookup */ /* Cleanup after lookup */
//ObpCleanupDirectoryLookup(&TempBuffer->LookupContext); ObpCleanupDirectoryLookup(&TempBuffer->LookupContext);
TempBuffer->LookupContext.Object = NULL;
} }
else else
{ {
@ -2589,6 +2586,9 @@ 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 after lookup */
ObpCleanupDirectoryLookup(&Context);
/* Remove query reference that we added */ /* Remove query reference that we added */
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo); if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
@ -2657,6 +2657,9 @@ 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 */
ObpCleanupDirectoryLookup(&Context);
/* Remove query reference that we added */ /* Remove query reference that we added */
if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo); if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);

View file

@ -282,10 +282,7 @@ ObPostPhase0:
ObpInitializeDirectoryLookup(&Context); ObpInitializeDirectoryLookup(&Context);
/* Lock it */ /* Lock it */
//ObpAcquireDirectoryLockExclusive(ObpTypeDirectoryObject, &Context); ObpAcquireDirectoryLockExclusive(ObpTypeDirectoryObject, &Context);
Context.Directory = ObpTypeDirectoryObject;
Context.DirectoryLocked = TRUE;
Context.LockStateSignature = 0xCCCC1234;
/* Loop the object types */ /* Loop the object types */
ListHead = &ObTypeObjectType->TypeList; ListHead = &ObTypeObjectType->TypeList;
@ -323,8 +320,7 @@ ObPostPhase0:
} }
/* Cleanup after lookup */ /* Cleanup after lookup */
//ObpCleanupDirectoryLookup(&Context); ObpCleanupDirectoryLookup(&Context);
Context.Object = NULL;
/* Initialize DOS Devices Directory and related Symbolic Links */ /* Initialize DOS Devices Directory and related Symbolic Links */
Status = ObpCreateDosDevicesDirectory(); Status = ObpCreateDosDevicesDirectory();

View file

@ -965,10 +965,7 @@ ObCreateObjectType(IN PUNICODE_STRING TypeName,
if (ObpTypeDirectoryObject) if (ObpTypeDirectoryObject)
{ {
/* Acquire the directory lock */ /* Acquire the directory lock */
//ObpAcquireDirectoryLockExclusive(ObpTypeDirectoryObject, &Context); ObpAcquireDirectoryLockExclusive(ObpTypeDirectoryObject, &Context);
Context.Directory = ObpTypeDirectoryObject;
Context.DirectoryLocked = TRUE;
Context.LockStateSignature = 0xCCCC1234;
/* Do the lookup */ /* Do the lookup */
if (ObpLookupEntryDirectory(ObpTypeDirectoryObject, if (ObpLookupEntryDirectory(ObpTypeDirectoryObject,
@ -978,7 +975,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; ObpCleanupDirectoryLookup(&Context);
return STATUS_OBJECT_NAME_COLLISION; return STATUS_OBJECT_NAME_COLLISION;
} }
} }
@ -990,7 +987,7 @@ ObCreateObjectType(IN PUNICODE_STRING TypeName,
if (!ObjectName.Buffer) if (!ObjectName.Buffer)
{ {
/* Out of memory, fail */ /* Out of memory, fail */
Context.Object = NULL; ObpCleanupDirectoryLookup(&Context);
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
@ -1007,9 +1004,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 */
ObpCleanupDirectoryLookup(&Context);
ExFreePool(ObjectName.Buffer); ExFreePool(ObjectName.Buffer);
return Status; return Status;
} }
@ -1138,7 +1134,8 @@ ObCreateObjectType(IN PUNICODE_STRING TypeName,
ObReferenceObject(ObpTypeDirectoryObject); ObReferenceObject(ObpTypeDirectoryObject);
} }
Context.Object = NULL; /* Cleanup the lookup context */
ObpCleanupDirectoryLookup(&Context);
/* Return the object type and success */ /* Return the object type and success */
*ObjectType = LocalObjectType; *ObjectType = LocalObjectType;
@ -1146,7 +1143,7 @@ ObCreateObjectType(IN PUNICODE_STRING TypeName,
} }
/* If we got here, then we failed */ /* If we got here, then we failed */
Context.Object = NULL; ObpCleanupDirectoryLookup(&Context);
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }

View file

@ -191,16 +191,14 @@ ObpDeleteNameCheck(IN PVOID Object)
if (!(ObjectHeader->HandleCount) && if (!(ObjectHeader->HandleCount) &&
(ObjectNameInfo) && (ObjectNameInfo) &&
(ObjectNameInfo->Name.Length) && (ObjectNameInfo->Name.Length) &&
(ObjectNameInfo->Directory) &&
!(ObjectHeader->Flags & OB_FLAG_PERMANENT)) !(ObjectHeader->Flags & OB_FLAG_PERMANENT))
{ {
/* Setup a lookup context */ /* Setup a lookup context */
ObpInitializeDirectoryLookup(&Context); ObpInitializeDirectoryLookup(&Context);
/* Lock the directory */ /* Lock the directory */
//ObpAcquireDirectoryLockExclusive(ObjectNameInfo->Directory, &Context); ObpAcquireDirectoryLockExclusive(ObjectNameInfo->Directory, &Context);
Context.Directory = ObjectNameInfo->Directory;
Context.DirectoryLocked = TRUE;
Context.LockStateSignature = 0xCCCC1234;
/* Do the lookup */ /* Do the lookup */
Object = ObpLookupEntryDirectory(ObjectNameInfo->Directory, Object = ObpLookupEntryDirectory(ObjectNameInfo->Directory,
@ -253,8 +251,7 @@ ObpDeleteNameCheck(IN PVOID Object)
} }
/* Cleanup after lookup */ /* Cleanup after lookup */
//ObpCleanupDirectoryLookup(&Context); ObpCleanupDirectoryLookup(&Context);
Context.Object = NULL;
/* Remove another query reference since we added one on top */ /* Remove another query reference since we added one on top */
ObpDecrementQueryReference(ObjectNameInfo); ObpDecrementQueryReference(ObjectNameInfo);
@ -573,10 +570,7 @@ ReparseNewDir:
if (InsertObject) if (InsertObject)
{ {
/* Lock the directory */ /* Lock the directory */
//ObpAcquireDirectoryLockExclusive(Directory, LookupContext); ObpAcquireDirectoryLockExclusive(Directory, LookupContext);
LookupContext->Directory = Directory;
LookupContext->DirectoryLocked = TRUE;
LookupContext->LockStateSignature = 0xCCCC1234;
} }
} }
@ -696,8 +690,7 @@ Reparse:
InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1); InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1);
/* Cleanup from the first lookup */ /* Cleanup from the first lookup */
//ObpCleanupDirectoryLookup(LookupContext); ObpCleanupDirectoryLookup(LookupContext);
LookupContext->Object = NULL;
/* Check if we have a referenced directory */ /* Check if we have a referenced directory */
if (ReferencedDirectory) if (ReferencedDirectory)
@ -863,8 +856,7 @@ Reparse:
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
/* Cleanup after lookup */ /* Cleanup after lookup */
//ObpCleanupDirectoryLookup(LookupContext); ObpCleanupDirectoryLookup(LookupContext);
LookupContext->Object = NULL;
} }
/* Check if we have a device map and dereference it if so */ /* Check if we have a device map and dereference it if so */

View file

@ -430,8 +430,7 @@ ObReferenceObjectByName(IN PUNICODE_STRING ObjectPath,
&Object); &Object);
/* Cleanup after lookup */ /* Cleanup after lookup */
//ObpCleanupDirectoryLookup(&Context); ObpCleanupDirectoryLookup(&Context);
Context.Object = NULL;
/* Check if the lookup succeeded */ /* Check if the lookup succeeded */
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))