⬢ DragonFlyBSD Kernel Audit
DF-3186 / fix.diff
← back to finding ↓ download raw
--- a/sys/vfs/hammer/hammer_vfsops.c
+++ b/sys/vfs/hammer/hammer_vfsops.c
@@ -662,9 +662,22 @@ hammer_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
 	rootvol = hammer_get_root_volume(hmp, &error);
 	if (error)
 		goto failed;
 
+	/*
+	 * The UNDO reinitialization loop in hammer_upgrade_undo_4()
+	 * (hammer_undo.c:381) steps in HAMMER_UNDO_ALIGN (512) increments
+	 * from HAMMER_ENCODE_UNDO(0) and terminates only on exact equality
+	 * with the on-disk UNDO alloc_offset.  Reject headers whose
+	 * alloc_offset is not UNDO_ALIGN-congruent so a corrupted or
+	 * crafted header cannot turn that loop (executed under
+	 * finalize_lock + sync_lock) non-terminating.
+	 */
+	{
+		hammer_blockmap_t undomap;
+		undomap = &rootvol->ondisk->vol0_blockmap[HAMMER_ZONE_UNDO_INDEX];
+		if (undomap->alloc_offset & HAMMER_UNDO_MASK64) {
+			hkprintf("Illegal UNDO alloc_offset alignment\n");
+			error = EINVAL;
+			goto failed;
+		}
+	}
+
 	/*
 	 * Perform any necessary UNDO operations.  The recovery code does
 	 * call hammer_undo_lookup() so we have to pre-cache the blockmap,