--- 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,