⬢ DragonFlyBSD Kernel Audit
DF-3253 / fix.diff
← back to finding ↓ download raw
--- a/sys/vfs/hpfs/hpfs_hash.c	2026-09-09 14:23:15.467586441 +0000
+++ b/sys/vfs/hpfs/hpfs_hash.c	2026-09-09 14:23:15.483586242 +0000
@@ -129,6 +129,20 @@
 		}
 
 		/*
+		 * DF-3253: hpfs_vget publishes nodes into the hash before
+		 * validating them (bread + FN_MAGIC) and its error paths
+		 * vx_put() without unhashing.  Never hand out a node that
+		 * is still marked H_INVAL -- its h_fn is either not yet
+		 * initialized (bread failed) or was already rejected.
+		 * The retry is bounded because failed creators now unhash
+		 * the node (hpfs_vfsops.c DF-3253 fix).
+		 */
+		if (hp->h_flag & H_INVAL) {
+			vput(vp);
+			goto loop;
+		}
+
+		/*
 		 * Or if the vget fails (due to a race)
 		 */
 		lwkt_reltoken(&hpfs_hphash_token);
--- a/sys/vfs/hpfs/hpfs_vfsops.c	2026-09-09 14:21:27.496928348 +0000
+++ b/sys/vfs/hpfs/hpfs_vfsops.c	2026-09-09 14:23:15.495586092 +0000
@@ -529,6 +529,7 @@
 	error = bread(hpmp->hpm_devvp, dbtodoff(ino), FNODESIZE, &bp);
 	if (error) {
 		kprintf("hpfs_vget: can't read ino %"PRId64"\n",ino);
+		hpfs_hphashrem(hp);	/* DF-3253: don't leave H_INVAL hashed */
 		vx_put(vp);
 		return (error);
 	}
@@ -537,6 +538,7 @@
 
 	if (hp->h_fn.fn_magic != FN_MAGIC) {
 		kprintf("hpfs_vget: MAGIC DOESN'T MATCH\n");
+		hpfs_hphashrem(hp);	/* DF-3253: don't leave H_INVAL hashed */
 		vx_put(vp);
 		return (EINVAL);
 	}