DragonFlyBSD Kernel Audit
DF-0886 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/vfs/autofs/autofs_vnops.c b/sys/vfs/autofs/autofs_vnops.c
--- a/sys/vfs/autofs/autofs_vnops.c
+++ b/sys/vfs/autofs/autofs_vnops.c
@@ -586,16 +586,24 @@
 		return (0);
 	}
 
-	mtx_unlock_ex(&anp->an_vnode_lock);
-
+	/*
+	 * Hold an_vnode_lock across the sleepable getnewvnode() call to
+	 * serialize vnode creation for this node.  mtx_t is a sleeping
+	 * mutex, so this is safe and prevents the create race where two
+	 * threads both observed an_vnode == NULL, both entered
+	 * getnewvnode(), and the loser tripped the KASSERT below (or,
+	 * without INVARIANTS, leaked a vnode + corrupted reclaim state).
+	 */
 	error = getnewvnode(VT_AUTOFS, mp, &vp, VLKTIMEOUT, LK_CANRECURSE);
-	if (error)
+	if (error) {
+		mtx_unlock_ex(&anp->an_vnode_lock);
 		return (error);
+	}
 	vp->v_type = VDIR;
 	vp->v_data = anp;
 
-	KASSERT(anp->an_vnode == NULL, ("lost race"));
 	anp->an_vnode = vp;
+	mtx_unlock_ex(&anp->an_vnode_lock);
 	vx_downgrade(vp);	/* downgrade VX lock to VN lock */
 	*vpp = vp;