On Sat, Aug 1, 2026 at 6:55 AM Bryam Vargas via B4 Relay <[email protected]> wrote: > > From: Bryam Vargas <[email protected]> > > array_block_check() can only compare the header against itself, so a block > with value_size 4 and max_entries 1018 is internally consistent and passes. > dm-cache keeps two arrays -- mappings at 8 bytes and hints at 4 -- and the > roots for both live in the superblock. Point the mappings root at a hint > block and __load_mappings() walks it through an info whose value size is 8, > so element_at() strides 8 bytes over 4-byte entries and reaches offset 8160 > of a 4096-byte block. > > get_ablock() and __shadow_ablock() are the two places that hold the block > and the caller at once. Reject there when the two value sizes disagree. > Arrays only ever read their own blocks, so this fires on crafted metadata > only. > > Fixes: 6513c29f44f2 ("dm persistent data: add transactional array") > Suggested-by: Ming-Hung Tsai <[email protected]> > Cc: [email protected] > Signed-off-by: Bryam Vargas <[email protected]>
Reviewed-by: Ming-Hung Tsai <[email protected]> The fix addresses more than crafted metadata. A lost write on disk drives can cause a stale block that was freed as a hint block, triggering this out-of-bounds access issue.

