--- a/sys/vfs/hammer/hammer_undo.c +++ b/sys/vfs/hammer/hammer_undo.c @@ -62,6 +62,24 @@ hammer_off_t result_offset; KKASSERT(hammer_is_zone_undo(zone3_off)); + + /* + * DF-3040: the zone-3 offset indexes the fixed 128-entry + * vol0_undo_array in the root volume header + * (hammer_xlate_to_undo, hammer_disk.h). Every bound currently + * applied to zone-3 offsets (recover stage1, the KKASSERTs below) + * is derived from the same attacker-controlled vol0_blockmap[3], + * so a crafted header can push the array index far past the array + * and past the 16KB header buffer (kernel heap OOB read). + * Reject any offset outside the HAMMER_MAX_UNDO_BIGBLOCKS range + * the on-disk format actually supports. + */ + if (zone3_off >= HAMMER_ENCODE_UNDO( + (hammer_off_t)HAMMER_MAX_UNDO_BIGBLOCKS * + HAMMER_BIGBLOCK_SIZE64)) { + *errorp = EIO; + return(0); + } root_volume = hammer_get_root_volume(hmp, errorp); if (*errorp) return(0);