From b27d89c3224c2f6d1d79e7b40dd461ab639535cd Mon Sep 17 00:00:00 2001 From: Ramesh Adhikari Date: Sun, 26 Apr 2026 22:41:19 +0530 Subject: [PATCH] block: fix infinite loop in badblocks_clear() An infinite loop can occur in _badblocks_clear() when BB_OFFSET(p[prev + 1]) equals bad.start, resulting in len = 0. This causes the update_sectors loop to spin forever without making progress: s += 0; // no advancement sectors -= 0; // stays positive goto re_clear; // infinite loop The bug exists in two code paths: 1. _badblocks_clear() at line 1153 (behind overlap check) 2. _badblocks_check() at line 1240 (behind overlap check) Add checks in both functions to ensure len is non-zero before entering the loop. Signed-off-by: Ramesh Adhikari --- block/badblocks.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/block/badblocks.c b/block/badblocks.c index ece64e76fe8ff..1c6728866f95a 100644 --- a/block/badblocks.c +++ b/block/badblocks.c @@ -1151,6 +1151,10 @@ static bool _badblocks_clear(struct badblocks *bb, sector_t s, sector_t sectors) /* Not front overlap, but behind overlap */ if ((prev + 1) < bb->count && overlap_behind(bb, &bad, prev + 1)) { len = BB_OFFSET(p[prev + 1]) - bad.start; + if (len == 0) { + pr_warn_once("badblocks_clear: zero-length segment detected\n"); + len = 1; + } hint = prev + 1; /* Clear non-bad range should be treated as successful */ cleared++; @@ -1234,6 +1238,10 @@ static int _badblocks_check(struct badblocks *bb, sector_t s, sector_t sectors, /* Not front overlap, but behind overlap */ if ((prev + 1) < bb->count && overlap_behind(bb, &bad, prev + 1)) { len = BB_OFFSET(p[prev + 1]) - bad.start; + if (len == 0) { + pr_warn_once("badblocks_check: zero-length segment detected\n"); + len = 1; + } hint = prev + 1; goto update_sectors; }