too_many_discard_blocks() uses sector_div(), whose divisor is a u32. discard_block_size is a 64-bit sector_t that calculate_discard_block_size() keeps doubling, so once it reaches a multiple of 2^32 the divisor is truncated to 0 and the division traps with a divide error. Smaller values above 2^32 are also silently truncated, giving a wrong quotient. This needs an origin of more than 2^45 sectors, which is unrealistic (this is a thing still in 2026!!) for a real device but reachable with a fuzzer. Switching the div operation to one that uses 64 bits divisor would cause regression, so we just limit the value of cache->discard_block_size to U32_MAX. Reported-by: syzbot+3e16980543e238b95bd1@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=3e16980543e238b95bd1 Fixes: 08b184514f65 (" dm cache: revert "prevent corruption caused by discard_block_size > cache_block_size" ") Tested-by: syzbot+3e16980543e238b95bd1@syzkaller.appspotmail.com Cc: stable@vger.kernel.org Signed-off-by: Drif Abdelmalek Mohamed Said --- drivers/md/dm-cache-target.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index 1a5072425c4a..b51ceca60afc 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -2383,6 +2383,8 @@ static int create_cache_policy(struct cache *cache, struct cache_args *ca, static bool too_many_discard_blocks(sector_t discard_block_size, sector_t origin_size) { + if (discard_block_size > U32_MAX / 2) + return false; (void) sector_div(origin_size, discard_block_size); return origin_size > MAX_DISCARD_BLOCKS; -- 2.47.3