[NTOS:CM] Lock the cached KCB before removing it from cache entries
authorGeorge Bișoc <george.bisoc@reactos.org>
Sat, 23 Mar 2024 19:28:01 +0000 (20:28 +0100)
committerGeorge Bișoc <george.bisoc@reactos.org>
Sun, 24 Mar 2024 18:03:43 +0000 (19:03 +0100)
- Annotate the CmpEnumerateOpenSubKeys function with SAL2
- When removing an orphaned cached KCB, ensure that it is locked before clearing it from cache table entries

ntoskrnl/config/cmapi.c
ntoskrnl/config/ntapi.c
ntoskrnl/include/internal/cm.h

index 4d4edfd..944b469 100644 (file)
@@ -2242,7 +2242,7 @@ CmUnloadKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
     {
         if (Flags != REG_FORCE_UNLOAD)
         {
-            if (CmpEnumerateOpenSubKeys(Kcb, FALSE, FALSE) != 0)
+            if (CmpEnumerateOpenSubKeys(Kcb, FALSE, FALSE, FALSE) != 0)
             {
                 /* There are open subkeys but we don't force hive unloading, fail */
                 Hive->HiveFlags &= ~HIVE_IS_UNLOADING;
@@ -2252,7 +2252,7 @@ CmUnloadKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
         else
         {
             DPRINT1("CmUnloadKey: Force unloading is HALF-IMPLEMENTED, expect dangling KCBs problems!\n");
-            if (CmpEnumerateOpenSubKeys(Kcb, TRUE, TRUE) != 0)
+            if (CmpEnumerateOpenSubKeys(Kcb, TRUE, TRUE, TRUE) != 0)
             {
                 /* There are open subkeys that we cannot force to unload, fail */
                 Hive->HiveFlags &= ~HIVE_IS_UNLOADING;
@@ -2340,9 +2340,10 @@ CmUnloadKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
 ULONG
 NTAPI
 CmpEnumerateOpenSubKeys(
-    IN PCM_KEY_CONTROL_BLOCK RootKcb,
-    IN BOOLEAN RemoveEmptyCacheEntries,
-    IN BOOLEAN DereferenceOpenedEntries)
+    _In_ PCM_KEY_CONTROL_BLOCK RootKcb,
+    _In_ BOOLEAN LockHeldExclusively,
+    _In_ BOOLEAN RemoveEmptyCacheEntries,
+    _In_ BOOLEAN DereferenceOpenedEntries)
 {
     PCM_KEY_HASH Entry;
     PCM_KEY_CONTROL_BLOCK CachedKcb;
@@ -2430,11 +2431,20 @@ CmpEnumerateOpenSubKeys(
                     }
                     else if ((CachedKcb->RefCount == 0) && RemoveEmptyCacheEntries)
                     {
+                        /* Lock the cached KCB of subkey before removing it from cache entries */
+                        if (!LockHeldExclusively)
+                            CmpAcquireKcbLockExclusive(CachedKcb);
+
                         /* Remove the current key from the delayed close list */
                         CmpRemoveFromDelayedClose(CachedKcb);
 
                         /* Remove the current cache entry */
-                        CmpCleanUpKcbCacheWithLock(CachedKcb, TRUE);
+                        // Lock is either held by ourselves or registry is locked exclusively
+                        CmpCleanUpKcbCacheWithLock(CachedKcb, LockHeldExclusively);
+
+                        /* Unlock the cached KCB if it was done by ourselves */
+                        if (!LockHeldExclusively)
+                            CmpReleaseKcbLock(CachedKcb);
 
                         /* Restart, because the hash list has changed */
                         Entry = CmpCacheTable[i].Entry;
index 5bf9ec5..6748326 100644 (file)
@@ -1565,7 +1565,7 @@ NtQueryOpenSubKeys(IN POBJECT_ATTRIBUTES TargetKey,
 
     /* Call the internal API */
     SubKeys = CmpEnumerateOpenSubKeys(KeyBody->KeyControlBlock,
-                                      FALSE, FALSE);
+                                      TRUE, FALSE, FALSE);
 
     /* Unlock the registry */
     CmpUnlockRegistry();
index 7657fc7..a211862 100644 (file)
@@ -1333,9 +1333,10 @@ CmUnloadKey(
 ULONG
 NTAPI
 CmpEnumerateOpenSubKeys(
-    IN PCM_KEY_CONTROL_BLOCK RootKcb,
-    IN BOOLEAN RemoveEmptyCacheEntries,
-    IN BOOLEAN DereferenceOpenedEntries
+    _In_ PCM_KEY_CONTROL_BLOCK RootKcb,
+    _In_ BOOLEAN LockHeldExclusively,
+    _In_ BOOLEAN RemoveEmptyCacheEntries,
+    _In_ BOOLEAN DereferenceOpenedEntries
 );
 
 HCELL_INDEX