From c7e9309ac30018a1345f4417869659477b397c95 Mon Sep 17 00:00:00 2001 From: Ramesh Adhikari Date: Sun, 26 Apr 2026 22:56:40 +0530 Subject: [PATCH] block: fix infinite loop in badblocks_clear() and badblocks_check() An infinite loop can occur in both _badblocks_clear() and _badblocks_check() when BB_OFFSET() equals the start position, 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 three code paths: 1. _badblocks_clear() at line 1100 (start before all badblocks) 2. _badblocks_clear() at line 1153 (behind overlap check) 3. _badblocks_check() at line 1240 (behind overlap check) Add checks in all three locations to ensure len is non-zero before entering the loop. Signed-off-by: Ramesh Adhikari --- block/badblocks.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/block/badblocks.c b/block/badblocks.c index ece64e76fe8ff..9dd2d921e1b09 100644 --- a/block/badblocks.c +++ b/block/badblocks.c @@ -1098,6 +1098,10 @@ static bool _badblocks_clear(struct badblocks *bb, sector_t s, sector_t sectors) if (prev < 0) { if (overlap_behind(bb, &bad, 0)) { len = BB_OFFSET(p[0]) - s; + if (len == 0) { + pr_warn_once("badblocks_clear: zero-length at start\n"); + len = 1; + } hint = 0; } else { len = sectors; @@ -1151,6 +1155,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 +1242,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; }