Skip to content

Commit c7e9309

Browse files
SilentSobskawasaki
authored andcommitted
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 <[email protected]>
1 parent 857ada9 commit c7e9309

1 file changed

Lines changed: 12 additions & 0 deletions

File tree

block/badblocks.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,6 +1098,10 @@ static bool _badblocks_clear(struct badblocks *bb, sector_t s, sector_t sectors)
10981098
if (prev < 0) {
10991099
if (overlap_behind(bb, &bad, 0)) {
11001100
len = BB_OFFSET(p[0]) - s;
1101+
if (len == 0) {
1102+
pr_warn_once("badblocks_clear: zero-length at start\n");
1103+
len = 1;
1104+
}
11011105
hint = 0;
11021106
} else {
11031107
len = sectors;
@@ -1151,6 +1155,10 @@ static bool _badblocks_clear(struct badblocks *bb, sector_t s, sector_t sectors)
11511155
/* Not front overlap, but behind overlap */
11521156
if ((prev + 1) < bb->count && overlap_behind(bb, &bad, prev + 1)) {
11531157
len = BB_OFFSET(p[prev + 1]) - bad.start;
1158+
if (len == 0) {
1159+
pr_warn_once("badblocks_clear: zero-length segment detected\n");
1160+
len = 1;
1161+
}
11541162
hint = prev + 1;
11551163
/* Clear non-bad range should be treated as successful */
11561164
cleared++;
@@ -1234,6 +1242,10 @@ static int _badblocks_check(struct badblocks *bb, sector_t s, sector_t sectors,
12341242
/* Not front overlap, but behind overlap */
12351243
if ((prev + 1) < bb->count && overlap_behind(bb, &bad, prev + 1)) {
12361244
len = BB_OFFSET(p[prev + 1]) - bad.start;
1245+
if (len == 0) {
1246+
pr_warn_once("badblocks_check: zero-length segment detected\n");
1247+
len = 1;
1248+
}
12371249
hint = prev + 1;
12381250
goto update_sectors;
12391251
}

0 commit comments

Comments
 (0)