⬢ DragonFlyBSD Kernel Audit
DF-2660 / fix.diff
← back to finding ↓ download raw
--- a/sys/vfs/hammer2/hammer2_synchro.c	2026-10-15 07:16:23.700535111 +0000
+++ b/sys/vfs/hammer2/hammer2_synchro.c	2026-10-15 07:16:39.628330073 +0000
@@ -755,7 +755,23 @@
 				     &error,
 				     HAMMER2_LOOKUP_NODIRECT |
 				     HAMMER2_LOOKUP_ALWAYS);
-	KKASSERT(chain == NULL);
+	if (chain) {
+		/*
+		 * TOCTOU: the scan ran with the inode unlocked and the
+		 * parent shared, so a concurrent VOP create/rename on the
+		 * mounted rw cluster can have inserted the same key on
+		 * our column between the scan and this exclusive
+		 * re-lookup.  The racing creator wrote the key to ALL
+		 * columns in one cluster transaction, so dropping our
+		 * stale insert keeps the columns consistent; retry via
+		 * EAGAIN.
+		 */
+		hammer2_chain_unlock(chain);
+		hammer2_chain_drop(chain);
+		chain = NULL;
+		error = HAMMER2_ERROR_EAGAIN;
+		goto failed;
+	}
 
 	chain = NULL;
 	error = hammer2_chain_create(parentp, &chain, NULL, thr->pmp,