Zone-end wrap check uses exact equality while unvalidated layer2->append_off / blockmap next_offset / hint can push next_offset past the zone boundary — allocations returned outside the requested zone on production kernels
Summary
hammer_blockmap_alloc/reserve terminate their offset walk only on exact equality 'next_offset == HAMMER_ZONE_ENCODE(zone+1,0)' (:162/:466), but the walk advances by unvalidated disk-derived values: 'next_offset += layer2->append_off - offset' (:256/:538, append_off a raw uint32 from media - up to ~4GB per iteration, multiple iterations accumulate) and 'next_offset += resv->append_off - offset' (:312/:573). A crafted layer2 append_off (forgeable CRC) - or a crafted vol0_blockmap[].next_offset / caller hint (the volume header CRC is never verified, DF-3042) - moves next_offset past the zone end without ever equaling it, carrying into the zone nibble (zone 8->9 etc.); the entry-side guards KKASSERT(HAMMER_ZONE_DECODE(blockmap->next_offset) == zone) (:137/:449) are INVARIANTS-only. Result: alloc returns offsets in a foreign zone (file data placed into META/BTREE big-blocks), breaking the zone-separation invariant the rest of HAMMER relies on; INVARIANTS kernels panic at one of the many KKASSERTs, production kernels silently store cross-zone data_offsets. All I/O still funnels through the buffer cache with the 52-bit phys mask - impact confined to the attacker's own crafted fs (zone confusion, metadata/data cross-placement), no kernel memory unsafety. Code-trace only (Low). Fix: production zone checks at entry + re-check after each advance + layer2->append_off <= HAMMER_BIGBLOCK_SIZE.
No comments yet.