⬢ DragonFlyBSD Kernel Audit
DF-3180 / fix.diff
← back to finding ↓ download raw
--- a/sys/vfs/tmpfs/tmpfs_vfsops.c
+++ b/sys/vfs/tmpfs/tmpfs_vfsops.c
@@ -459,10 +459,21 @@
 		}
 	}
 
-	if (found)
+	if (found) {
+		/*
+		 * Pin the node so that a concurrent inactive/reclaim cannot
+		 * free it out from under tmpfs_alloc_vp(), which may block
+		 * and thereby release the mount token.  Mirrors the pinning
+		 * done by tmpfs_unmount().  A reclaimed node will simply
+		 * return ENOENT via the TMPFS_VNODE_DOOMED check.
+		 */
+		atomic_add_int(&node->tn_links, 1);
 		rc = tmpfs_alloc_vp(mp, NULL, node, LK_EXCLUSIVE, vpp);
-
-	TMPFS_UNLOCK(tmp);
+		TMPFS_UNLOCK(tmp);
+		atomic_add_int(&node->tn_links, -1);
+	} else {
+		TMPFS_UNLOCK(tmp);
+	}
 
 	return (rc);
 }