DragonFlyBSD Kernel Audit
DF-2630 / fix.diff
← back to finding ↓ download raw
--- a/sys/vfs/hammer2/hammer2.h	2026-06-29 12:51:19.000000000 +0000
+++ b/sys/vfs/hammer2/hammer2.h	2026-08-29 01:18:27.847135212 +0000
@@ -1254,6 +1254,7 @@
  */
 #define HAMMER2_PMPF_SPMP	0x00000001
 #define HAMMER2_PMPF_EMERG	0x00000002	/* Emergency delete mode */
+#define HAMMER2_PMPF_ROOTFAILED	0x00000004	/* root quorum unreachable */
 
 #define HAMMER2_DIRTYCHAIN_WAITING	0x80000000
 #define HAMMER2_DIRTYCHAIN_MASK		0x7FFFFFFF
--- a/sys/vfs/hammer2/hammer2_vfsops.c	2026-06-29 12:51:19.000000000 +0000
+++ b/sys/vfs/hammer2/hammer2_vfsops.c	2026-08-29 01:18:27.871134910 +0000
@@ -112,6 +112,10 @@
 
 SYSCTL_INT(_vfs_hammer2, OID_AUTO, supported_version, CTLFLAG_RD,
 	   &hammer2_supported_version, 0, "");
+static int hammer2_root_timeout = 60;	/* secs; 0 = forever (legacy) */
+SYSCTL_INT(_vfs_hammer2, OID_AUTO, root_timeout, CTLFLAG_RW,
+	   &hammer2_root_timeout, 0,
+	   "max seconds VFS_ROOT waits for cluster quorum (0 = forever)");
 SYSCTL_INT(_vfs_hammer2, OID_AUTO, aux_flags, CTLFLAG_RW,
 	   &hammer2_aux_flags, 0, "");
 SYSCTL_INT(_vfs_hammer2, OID_AUTO, debug, CTLFLAG_RW,
@@ -1951,6 +1955,7 @@
 	hammer2_pfs_t *pmp;
 	struct vnode *vp;
 	int error;
+	int loops;
 
 	pmp = MPTOPMP(mp);
 	if (pmp->iroot == NULL) {
@@ -1960,7 +1965,19 @@
 		return EINVAL;
 	}
 
+	/*
+	 * DF-2630: A quorum failure is permanent for this pmp (e.g.
+	 * pfs_nmasters ingested from a forged/corrupt PFS inode exceeds
+	 * the number of attached chains).  Fail immediately instead of
+	 * re-waiting the full timeout on every lookup crossing the mount.
+	 */
+	if (pmp->flags & HAMMER2_PMPF_ROOTFAILED) {
+		*vpp = NULL;
+		return EIO;
+	}
+
 	error = 0;
+	loops = 0;
 	hammer2_inode_lock(pmp->iroot, HAMMER2_RESOLVE_SHARED);
 
 	while (pmp->inode_tid == 0) {
@@ -2008,6 +2025,18 @@
 		hammer2_inode_lock(pmp->iroot, HAMMER2_RESOLVE_SHARED);
 		if (error == EINTR)
 			break;
+		if (hammer2_root_timeout && ++loops >= hammer2_root_timeout) {
+			kprintf("hammer2 (%s): root quorum cannot be reached "
+				"(nmasters=%d nchains=%d), failing VFS_ROOT "
+				"after %ds\n",
+				mp->mnt_stat.f_mntfromname,
+				pmp->pfs_nmasters,
+				pmp->iroot->cluster.nchains,
+				hammer2_root_timeout);
+			atomic_set_int(&pmp->flags, HAMMER2_PMPF_ROOTFAILED);
+			error = EIO;
+			break;
+		}
 	}
 
 	if (error) {