CVE-2026-46045
Description
In the Linux kernel, the following vulnerability has been resolved:
md/md-llbitmap: skip reading rdevs that are not in_sync
When reading bitmap pages from member disks, the code iterates through all rdevs and attempts to read from the first available one. However, it only checks for raid_disk assignment and Faulty flag, missing the In_sync flag check.
This can cause bitmap data to be read from spare disks that are still being rebuilt and don't have valid bitmap information yet. Reading stale or uninitialized bitmap data from such disks can lead to incorrect dirty bit tracking, potentially causing data corruption during recovery or normal operation.
Add the In_sync flag check to ensure bitmap pages are only read from fully synchronized member disks that have valid bitmap data.
Affected products
2Patches
67701e68b5072md/md-llbitmap: skip reading rdevs that are not in_sync
1 file changed · +2 −2
drivers/md/md-llbitmap.c+2 −2 modifieddiff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index bf398d7476b35a..6b2d27de152856 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -459,7 +459,8 @@ static struct page *llbitmap_read_page(struct llbitmap *llbitmap, int idx) rdev_for_each(rdev, mddev) { sector_t sector; - if (rdev->raid_disk < 0 || test_bit(Faulty, &rdev->flags)) + if (rdev->raid_disk < 0 || test_bit(Faulty, &rdev->flags) || + !test_bit(In_sync, &rdev->flags)) continue; sector = mddev->bitmap_info.offset + -- cgit 1.3-korg
98623c7e2a51md/md-llbitmap: skip reading rdevs that are not in_sync
1 file changed · +2 −2
drivers/md/md-llbitmap.c+2 −2 modifieddiff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index bcb6eae1c711f6..a8fd81c274027d 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -459,7 +459,8 @@ static struct page *llbitmap_read_page(struct llbitmap *llbitmap, int idx) rdev_for_each(rdev, mddev) { sector_t sector; - if (rdev->raid_disk < 0 || test_bit(Faulty, &rdev->flags)) + if (rdev->raid_disk < 0 || test_bit(Faulty, &rdev->flags) || + !test_bit(In_sync, &rdev->flags)) continue; sector = mddev->bitmap_info.offset + -- cgit 1.3-korg
3115fa2f6297md/md-llbitmap: skip reading rdevs that are not in_sync
1 file changed · +2 −2
drivers/md/md-llbitmap.c+2 −2 modifieddiff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index bf398d7476b35a..6b2d27de152856 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -459,7 +459,8 @@ static struct page *llbitmap_read_page(struct llbitmap *llbitmap, int idx) rdev_for_each(rdev, mddev) { sector_t sector; - if (rdev->raid_disk < 0 || test_bit(Faulty, &rdev->flags)) + if (rdev->raid_disk < 0 || test_bit(Faulty, &rdev->flags) || + !test_bit(In_sync, &rdev->flags)) continue; sector = mddev->bitmap_info.offset + -- cgit 1.3-korg
3115fa2f6297md/md-llbitmap: skip reading rdevs that are not in_sync
1 file changed · +2 −2
drivers/md/md-llbitmap.c+2 −2 modifieddiff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index bf398d7476b35a..6b2d27de152856 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -459,7 +459,8 @@ static struct page *llbitmap_read_page(struct llbitmap *llbitmap, int idx) rdev_for_each(rdev, mddev) { sector_t sector; - if (rdev->raid_disk < 0 || test_bit(Faulty, &rdev->flags)) + if (rdev->raid_disk < 0 || test_bit(Faulty, &rdev->flags) || + !test_bit(In_sync, &rdev->flags)) continue; sector = mddev->bitmap_info.offset + -- cgit 1.3-korg
7701e68b5072md/md-llbitmap: skip reading rdevs that are not in_sync
1 file changed · +2 −2
drivers/md/md-llbitmap.c+2 −2 modifieddiff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index bf398d7476b35a..6b2d27de152856 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -459,7 +459,8 @@ static struct page *llbitmap_read_page(struct llbitmap *llbitmap, int idx) rdev_for_each(rdev, mddev) { sector_t sector; - if (rdev->raid_disk < 0 || test_bit(Faulty, &rdev->flags)) + if (rdev->raid_disk < 0 || test_bit(Faulty, &rdev->flags) || + !test_bit(In_sync, &rdev->flags)) continue; sector = mddev->bitmap_info.offset + -- cgit 1.3-korg
98623c7e2a51md/md-llbitmap: skip reading rdevs that are not in_sync
1 file changed · +2 −2
drivers/md/md-llbitmap.c+2 −2 modifieddiff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index bcb6eae1c711f6..a8fd81c274027d 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -459,7 +459,8 @@ static struct page *llbitmap_read_page(struct llbitmap *llbitmap, int idx) rdev_for_each(rdev, mddev) { sector_t sector; - if (rdev->raid_disk < 0 || test_bit(Faulty, &rdev->flags)) + if (rdev->raid_disk < 0 || test_bit(Faulty, &rdev->flags) || + !test_bit(In_sync, &rdev->flags)) continue; sector = mddev->bitmap_info.offset + -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"Missing In_sync flag check in llbitmap_read_page() allows bitmap data to be read from spare disks that are not fully synchronized."
Attack vector
An attacker who can trigger a RAID array rebuild (e.g., by causing a disk failure and replacement) can cause the md driver to read bitmap pages from a spare disk that is still being rebuilt and has not yet set the In_sync flag. The function llbitmap_read_page() in drivers/md/md-llbitmap.c iterates over all rdevs and only checks for raid_disk assignment and the Faulty flag, but does not check In_sync [patch_id=2660173]. This means the first available rdev that passes those two checks may be a spare disk with stale or uninitialized bitmap data. Reading such data leads to incorrect dirty bit tracking, which can cause data corruption during recovery or normal operation.
Affected code
The vulnerable code is in the function llbitmap_read_page() in drivers/md/md-llbitmap.c [patch_id=2660173]. The function iterates over all rdevs (raid devices) to find one from which to read bitmap pages, but its skip condition only checked `rdev->raid_disk < 0` and `test_bit(Faulty, &rdev->flags)`, missing the In_sync flag check.
What the fix does
The patch adds a check for the In_sync flag to the existing condition in llbitmap_read_page() [patch_id=2660173]. The original condition skipped rdevs that had no raid_disk assigned or were marked Faulty; the patch adds `!test_bit(In_sync, &rdev->flags)` so that spare disks still undergoing rebuild are also skipped. This ensures bitmap pages are only read from fully synchronized member disks that have valid bitmap data, preventing the use of stale or uninitialized bitmap information.
Preconditions
- configThe RAID array must be using the lockless bitmap (md-llbitmap) feature.
- inputA spare disk must be present in the array that is still being rebuilt (not yet In_sync).
- networkNo network precondition; this is a local kernel vulnerability triggered during RAID recovery operations.
Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
3News mentions
0No linked articles in our index yet.