[NTOS:OB] Clarify and fix the usage of the Obp*DirectoryLock*() and ObpReleaseLookupContextObject() functions.

- Disentangle the usage of ObpAcquireDirectoryLockExclusive() when it's
  used only for accessing a directory structure, or as part of a lookup
  operation.

  The Obp*DirectoryLock*() -- both shared and exclusive -- functions
  are only for locking an OB directory, for reading or writing its
  structure members.

  When performing lookup operations (insertions/deletions of entries
  within a directory), use a ObpAcquireLookupContextLock() function that
  exclusively locks the directory and saves extra lock state, that can
  be used by ObpReleaseLookupContextObject() for cleanup.

- Add documentation for these functions.
This commit is contained in:
Hermès Bélusca-Maïto 2021-09-25 00:03:56 +02:00
parent 19cdb521d2
commit 4c63ed5a7a
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
5 changed files with 93 additions and 29 deletions

View file

@ -169,15 +169,26 @@ ObpDereferenceNameInfo(IN POBJECT_HEADER_NAME_INFO HeaderNameInfo)
}
}
/**
* @brief
* Locks a directory for shared access.
* Used for reading members of the directory object.
*
* @param[in] Directory
* The directory to lock.
*
* @param[in] Context
* The lookup lock context.
*/
FORCEINLINE
VOID
ObpAcquireDirectoryLockShared(IN POBJECT_DIRECTORY Directory,
IN POBP_LOOKUP_CONTEXT Context)
{
/* It's not, set lock flag */
/* Update lock flag */
Context->LockStateSignature = OBP_LOCK_STATE_PRE_ACQUISITION_SHARED;
/* Lock it */
/* Acquire an shared directory lock */
KeEnterCriticalRegion();
ExAcquirePushLockShared(&Directory->Lock);
@ -185,6 +196,17 @@ ObpAcquireDirectoryLockShared(IN POBJECT_DIRECTORY Directory,
Context->LockStateSignature = OBP_LOCK_STATE_POST_ACQUISITION_SHARED;
}
/**
* @brief
* Locks a directory for exclusive access.
* Used for writing/reading members of the directory object.
*
* @param[in] Directory
* The directory to lock.
*
* @param[in] Context
* The lookup lock context.
*/
FORCEINLINE
VOID
ObpAcquireDirectoryLockExclusive(IN POBJECT_DIRECTORY Directory,
@ -197,14 +219,20 @@ ObpAcquireDirectoryLockExclusive(IN POBJECT_DIRECTORY Directory,
KeEnterCriticalRegion();
ExAcquirePushLockExclusive(&Directory->Lock);
/* Set the directory */
Context->Directory = Directory;
/* Update lock settings */
/* Update lock flag */
Context->LockStateSignature = OBP_LOCK_STATE_POST_ACQUISITION_EXCLUSIVE;
Context->DirectoryLocked = TRUE;
}
/**
* @brief
* Unlocks a previously shared or exclusively locked directory.
*
* @param[in] Directory
* The directory to unlock.
*
* @param[in] Context
* The lookup lock context.
*/
FORCEINLINE
VOID
ObpReleaseDirectoryLock(IN POBJECT_DIRECTORY Directory,
@ -216,6 +244,15 @@ ObpReleaseDirectoryLock(IN POBJECT_DIRECTORY Directory,
KeLeaveCriticalRegion();
}
/**
* @brief
* Initializes a new object directory lookup context.
* Used for lookup operations (insertions/deletions) in a directory.
* Employed in conjunction with the directory locking functions.
*
* @param[in] Context
* The new lookup context to initialize.
*/
FORCEINLINE
VOID
ObpInitializeLookupContext(IN POBP_LOOKUP_CONTEXT Context)
@ -227,6 +264,29 @@ ObpInitializeLookupContext(IN POBP_LOOKUP_CONTEXT Context)
Context->LockStateSignature = OBP_LOCK_STATE_INITIALIZED;
}
/**
* @brief
* Locks an object directory lookup context for performing
* lookup operations (insertions/deletions) in a directory.
* The directory is locked for exclusive access.
*
* @param[in] Context
* The lookup context to lock.
*
* @param[in] Directory
* The directory on which the lookup context applies.
*/
FORCEINLINE
VOID
ObpAcquireLookupContextLock(IN POBP_LOOKUP_CONTEXT Context,
IN POBJECT_DIRECTORY Directory)
{
/* Acquire an exclusive directory lock and save its lock state */
ObpAcquireDirectoryLockExclusive(Directory, Context);
Context->Directory = Directory;
Context->DirectoryLocked = TRUE;
}
FORCEINLINE
VOID
ObpReleaseLookupContextObject(IN POBP_LOOKUP_CONTEXT Context)
@ -234,14 +294,14 @@ ObpReleaseLookupContextObject(IN POBP_LOOKUP_CONTEXT Context)
POBJECT_HEADER ObjectHeader;
POBJECT_HEADER_NAME_INFO HeaderNameInfo;
/* Check if we had found an object */
/* Check if we had an object */
if (Context->Object)
{
/* Get the object name information */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Context->Object);
HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
/* release the name information */
/* Release the name information */
ObpDereferenceNameInfo(HeaderNameInfo);
/* Dereference the object */
@ -250,6 +310,14 @@ ObpReleaseLookupContextObject(IN POBP_LOOKUP_CONTEXT Context)
}
}
/**
* @brief
* Releases an initialized object directory lookup context.
* Unlocks it if necessary, and dereferences the underlying object.
*
* @param[in] Context
* The lookup context to release.
*/
FORCEINLINE
VOID
ObpReleaseLookupContext(IN POBP_LOOKUP_CONTEXT Context)
@ -257,7 +325,7 @@ ObpReleaseLookupContext(IN POBP_LOOKUP_CONTEXT Context)
/* Check if we came back with the directory locked */
if (Context->DirectoryLocked)
{
/* Release the lock */
/* Release the directory lock */
ObpReleaseDirectoryLock(Context->Directory, Context);
Context->Directory = NULL;
Context->DirectoryLocked = FALSE;

View file

@ -573,7 +573,7 @@ NtQueryDirectoryObject(IN HANDLE DirectoryHandle,
return Status;
}
/* Lock directory in shared mode */
/* Lock the directory in shared mode */
ObpAcquireDirectoryLockShared(Directory, &LookupContext);
/* Start at position 0 */

View file

@ -386,11 +386,9 @@ ObPostPhase0:
Status = NtClose(Handle);
if (!NT_SUCCESS(Status)) return FALSE;
/* Initialize lookup context */
/* Initialize the lookup context and lock it */
ObpInitializeLookupContext(&Context);
/* Lock it */
ObpAcquireDirectoryLockExclusive(ObpTypeDirectoryObject, &Context);
ObpAcquireLookupContextLock(&Context, ObpTypeDirectoryObject);
/* Loop the object types */
ListHead = &ObpTypeObjectType->TypeList;

View file

@ -1093,8 +1093,8 @@ ObCreateObjectType(IN PUNICODE_STRING TypeName,
/* Check if we've already created the directory of types */
if (ObpTypeDirectoryObject)
{
/* Acquire the directory lock */
ObpAcquireDirectoryLockExclusive(ObpTypeDirectoryObject, &Context);
/* Lock the lookup context */
ObpAcquireLookupContextLock(&Context, ObpTypeDirectoryObject);
/* Do the lookup */
if (ObpLookupEntryDirectory(ObpTypeDirectoryObject,
@ -1853,7 +1853,7 @@ NtSetInformationObject(IN HANDLE ObjectHandle,
OBP_LOOKUP_CONTEXT LookupContext;
ObpInitializeLookupContext(&LookupContext);
/* Set its session ID */
/* Set the directory session ID */
ObpAcquireDirectoryLockExclusive(Directory, &LookupContext);
Directory->SessionId = PsGetCurrentProcessSessionId();
ObpReleaseDirectoryLock(Directory, &LookupContext);

View file

@ -321,11 +321,9 @@ ObpDeleteNameCheck(IN PVOID Object)
(ObjectNameInfo->Directory) &&
!(ObjectHeader->Flags & OB_FLAG_PERMANENT))
{
/* Setup a lookup context */
/* Setup a lookup context and lock it */
ObpInitializeLookupContext(&Context);
/* Lock the directory */
ObpAcquireDirectoryLockExclusive(ObjectNameInfo->Directory, &Context);
ObpAcquireLookupContextLock(&Context, ObjectNameInfo->Directory);
/* Do the lookup */
Object = ObpLookupEntryDirectory(ObjectNameInfo->Directory,
@ -352,7 +350,7 @@ ObpDeleteNameCheck(IN PVOID Object)
ObpDeleteSymbolicLinkName(Object);
}
/* Check if the kernel exclusive is set */
/* Check if the kernel exclusive flag is set */
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
if ((ObjectNameInfo) &&
(ObjectNameInfo->QueryReferences & OB_FLAG_KERNEL_EXCLUSIVE))
@ -843,8 +841,8 @@ ParseFromRoot:
/* Check if we are inserting an object */
if (InsertObject)
{
/* Lock the directory */
ObpAcquireDirectoryLockExclusive(Directory, LookupContext);
/* Lock the lookup context */
ObpAcquireLookupContextLock(LookupContext, Directory);
}
}