CVE-2026-46095
Description
In the Linux kernel, the following vulnerability has been resolved:
md/md-llbitmap: raise barrier before state machine transition
Move the barrier raise operation before calling llbitmap_state_machine() in both llbitmap_start_write() and llbitmap_start_discard(). This ensures the barrier is in place before any state transitions occur, preventing potential race conditions where the state machine could complete before the barrier is properly raised.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
In the Linux kernel's md/llbitmap, a race condition due to misplaced barrier raise could allow state machine transition before barrier, leading to potential data corruption.
Vulnerability
A race condition exists in the Linux kernel's md/llbitmap driver. In functions llbitmap_start_write() and llbitmap_start_discard(), the barrier raise operation was performed after calling llbitmap_state_machine(). This ordering could allow the state machine to complete before the barrier is properly raised, leading to concurrent access issues. The vulnerability was introduced in versions prior to commit 9142f00a9287 [1].
Exploitation
An attacker would need local access to the system and the ability to trigger concurrent write or discard operations on an md device using the llbitmap. By racing these operations, the attacker could cause the state machine to transition without the required synchronization barrier.
Impact
Successful exploitation could lead to inconsistent state in the llbitmap, potentially resulting in data corruption or system instability. The exact impact depends on the nature of the state machine transition and the concurrent operations.
Mitigation
The issue is fixed in Linux kernel commit 9142f00a9287 [1]. Users should apply this patch or upgrade to a kernel version that includes it. No workaround is available.
AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
1Patches
69142f00a9287md/md-llbitmap: raise barrier before state machine transition
1 file changed · +4 −5
drivers/md/md-llbitmap.c+4 −5 modifieddiff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index a8fd81c274027d..0526e742062acb 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -1070,12 +1070,12 @@ static void llbitmap_start_write(struct mddev *mddev, sector_t offset, int page_start = (start + BITMAP_DATA_OFFSET) >> PAGE_SHIFT; int page_end = (end + BITMAP_DATA_OFFSET) >> PAGE_SHIFT; - llbitmap_state_machine(llbitmap, start, end, BitmapActionStartwrite); - while (page_start <= page_end) { llbitmap_raise_barrier(llbitmap, page_start); page_start++; } + + llbitmap_state_machine(llbitmap, start, end, BitmapActionStartwrite); } static void llbitmap_end_write(struct mddev *mddev, sector_t offset, @@ -1102,12 +1102,12 @@ static void llbitmap_start_discard(struct mddev *mddev, sector_t offset, int page_start = (start + BITMAP_DATA_OFFSET) >> PAGE_SHIFT; int page_end = (end + BITMAP_DATA_OFFSET) >> PAGE_SHIFT; - llbitmap_state_machine(llbitmap, start, end, BitmapActionDiscard); - while (page_start <= page_end) { llbitmap_raise_barrier(llbitmap, page_start); page_start++; } + + llbitmap_state_machine(llbitmap, start, end, BitmapActionDiscard); } static void llbitmap_end_discard(struct mddev *mddev, sector_t offset, -- cgit 1.3-korg
ef4ca3d4bf09md/md-llbitmap: raise barrier before state machine transition
1 file changed · +4 −5
drivers/md/md-llbitmap.c+4 −5 modifieddiff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index 6b2d27de152856..cdfecaca216bfc 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -1070,12 +1070,12 @@ static void llbitmap_start_write(struct mddev *mddev, sector_t offset, int page_start = (start + BITMAP_DATA_OFFSET) >> PAGE_SHIFT; int page_end = (end + BITMAP_DATA_OFFSET) >> PAGE_SHIFT; - llbitmap_state_machine(llbitmap, start, end, BitmapActionStartwrite); - while (page_start <= page_end) { llbitmap_raise_barrier(llbitmap, page_start); page_start++; } + + llbitmap_state_machine(llbitmap, start, end, BitmapActionStartwrite); } static void llbitmap_end_write(struct mddev *mddev, sector_t offset, @@ -1102,12 +1102,12 @@ static void llbitmap_start_discard(struct mddev *mddev, sector_t offset, int page_start = (start + BITMAP_DATA_OFFSET) >> PAGE_SHIFT; int page_end = (end + BITMAP_DATA_OFFSET) >> PAGE_SHIFT; - llbitmap_state_machine(llbitmap, start, end, BitmapActionDiscard); - while (page_start <= page_end) { llbitmap_raise_barrier(llbitmap, page_start); page_start++; } + + llbitmap_state_machine(llbitmap, start, end, BitmapActionDiscard); } static void llbitmap_end_discard(struct mddev *mddev, sector_t offset, -- cgit 1.3-korg
9701d51dd378md/md-llbitmap: raise barrier before state machine transition
1 file changed · +4 −5
drivers/md/md-llbitmap.c+4 −5 modifieddiff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index 6b2d27de152856..cdfecaca216bfc 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -1070,12 +1070,12 @@ static void llbitmap_start_write(struct mddev *mddev, sector_t offset, int page_start = (start + BITMAP_DATA_OFFSET) >> PAGE_SHIFT; int page_end = (end + BITMAP_DATA_OFFSET) >> PAGE_SHIFT; - llbitmap_state_machine(llbitmap, start, end, BitmapActionStartwrite); - while (page_start <= page_end) { llbitmap_raise_barrier(llbitmap, page_start); page_start++; } + + llbitmap_state_machine(llbitmap, start, end, BitmapActionStartwrite); } static void llbitmap_end_write(struct mddev *mddev, sector_t offset, @@ -1102,12 +1102,12 @@ static void llbitmap_start_discard(struct mddev *mddev, sector_t offset, int page_start = (start + BITMAP_DATA_OFFSET) >> PAGE_SHIFT; int page_end = (end + BITMAP_DATA_OFFSET) >> PAGE_SHIFT; - llbitmap_state_machine(llbitmap, start, end, BitmapActionDiscard); - while (page_start <= page_end) { llbitmap_raise_barrier(llbitmap, page_start); page_start++; } + + llbitmap_state_machine(llbitmap, start, end, BitmapActionDiscard); } static void llbitmap_end_discard(struct mddev *mddev, sector_t offset, -- cgit 1.3-korg
9701d51dd378md/md-llbitmap: raise barrier before state machine transition
1 file changed · +4 −5
drivers/md/md-llbitmap.c+4 −5 modifieddiff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index 6b2d27de152856..cdfecaca216bfc 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -1070,12 +1070,12 @@ static void llbitmap_start_write(struct mddev *mddev, sector_t offset, int page_start = (start + BITMAP_DATA_OFFSET) >> PAGE_SHIFT; int page_end = (end + BITMAP_DATA_OFFSET) >> PAGE_SHIFT; - llbitmap_state_machine(llbitmap, start, end, BitmapActionStartwrite); - while (page_start <= page_end) { llbitmap_raise_barrier(llbitmap, page_start); page_start++; } + + llbitmap_state_machine(llbitmap, start, end, BitmapActionStartwrite); } static void llbitmap_end_write(struct mddev *mddev, sector_t offset, @@ -1102,12 +1102,12 @@ static void llbitmap_start_discard(struct mddev *mddev, sector_t offset, int page_start = (start + BITMAP_DATA_OFFSET) >> PAGE_SHIFT; int page_end = (end + BITMAP_DATA_OFFSET) >> PAGE_SHIFT; - llbitmap_state_machine(llbitmap, start, end, BitmapActionDiscard); - while (page_start <= page_end) { llbitmap_raise_barrier(llbitmap, page_start); page_start++; } + + llbitmap_state_machine(llbitmap, start, end, BitmapActionDiscard); } static void llbitmap_end_discard(struct mddev *mddev, sector_t offset, -- cgit 1.3-korg
ef4ca3d4bf09md/md-llbitmap: raise barrier before state machine transition
1 file changed · +4 −5
drivers/md/md-llbitmap.c+4 −5 modifieddiff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index 6b2d27de152856..cdfecaca216bfc 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -1070,12 +1070,12 @@ static void llbitmap_start_write(struct mddev *mddev, sector_t offset, int page_start = (start + BITMAP_DATA_OFFSET) >> PAGE_SHIFT; int page_end = (end + BITMAP_DATA_OFFSET) >> PAGE_SHIFT; - llbitmap_state_machine(llbitmap, start, end, BitmapActionStartwrite); - while (page_start <= page_end) { llbitmap_raise_barrier(llbitmap, page_start); page_start++; } + + llbitmap_state_machine(llbitmap, start, end, BitmapActionStartwrite); } static void llbitmap_end_write(struct mddev *mddev, sector_t offset, @@ -1102,12 +1102,12 @@ static void llbitmap_start_discard(struct mddev *mddev, sector_t offset, int page_start = (start + BITMAP_DATA_OFFSET) >> PAGE_SHIFT; int page_end = (end + BITMAP_DATA_OFFSET) >> PAGE_SHIFT; - llbitmap_state_machine(llbitmap, start, end, BitmapActionDiscard); - while (page_start <= page_end) { llbitmap_raise_barrier(llbitmap, page_start); page_start++; } + + llbitmap_state_machine(llbitmap, start, end, BitmapActionDiscard); } static void llbitmap_end_discard(struct mddev *mddev, sector_t offset, -- cgit 1.3-korg
9142f00a9287md/md-llbitmap: raise barrier before state machine transition
1 file changed · +4 −5
drivers/md/md-llbitmap.c+4 −5 modifieddiff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index a8fd81c274027d..0526e742062acb 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -1070,12 +1070,12 @@ static void llbitmap_start_write(struct mddev *mddev, sector_t offset, int page_start = (start + BITMAP_DATA_OFFSET) >> PAGE_SHIFT; int page_end = (end + BITMAP_DATA_OFFSET) >> PAGE_SHIFT; - llbitmap_state_machine(llbitmap, start, end, BitmapActionStartwrite); - while (page_start <= page_end) { llbitmap_raise_barrier(llbitmap, page_start); page_start++; } + + llbitmap_state_machine(llbitmap, start, end, BitmapActionStartwrite); } static void llbitmap_end_write(struct mddev *mddev, sector_t offset, @@ -1102,12 +1102,12 @@ static void llbitmap_start_discard(struct mddev *mddev, sector_t offset, int page_start = (start + BITMAP_DATA_OFFSET) >> PAGE_SHIFT; int page_end = (end + BITMAP_DATA_OFFSET) >> PAGE_SHIFT; - llbitmap_state_machine(llbitmap, start, end, BitmapActionDiscard); - while (page_start <= page_end) { llbitmap_raise_barrier(llbitmap, page_start); page_start++; } + + llbitmap_state_machine(llbitmap, start, end, BitmapActionDiscard); } static void llbitmap_end_discard(struct mddev *mddev, sector_t offset, -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"Incorrect ordering of barrier raise and state machine call in llbitmap_start_write() and llbitmap_start_discard() allows the state machine to complete before the per-page barrier is raised, creating a race window."
Attack vector
An attacker who can trigger concurrent I/O operations on an MD device using the lockless bitmap (md-llbitmap) can exploit the reversed ordering in llbitmap_start_write() and llbitmap_start_discard(). In the vulnerable code, llbitmap_state_machine() runs before llbitmap_raise_barrier() for the affected page range, meaning the state transition (e.g., BitmapActionStartwrite or BitmapActionDiscard) can complete without the barrier protecting the bitmap page. A concurrent thread performing a conflicting operation on the same bitmap region can then observe or modify bitmap state while it is in an inconsistent mid-transition state, leading to data corruption or incorrect bitmap tracking.
Affected code
The bug is in drivers/md/md-llbitmap.c in the functions llbitmap_start_write() and llbitmap_start_discard() [patch_id=2659745][patch_id=2659746][patch_id=2659747][patch_id=2659742][patch_id=2659743][patch_id=2659744]. Both functions called llbitmap_state_machine() before the while loop that calls llbitmap_raise_barrier() for each page in the range.
What the fix does
The patch swaps the order of operations in both llbitmap_start_write() and llbitmap_start_discard() inside drivers/md/md-llbitmap.c [patch_id=2659745][patch_id=2659746][patch_id=2659747][patch_id=2659742][patch_id=2659743][patch_id=2659744]. Previously, llbitmap_state_machine() was called first, then the per-page barrier was raised in a loop. The fix moves the barrier-raising loop before the state machine call, ensuring that every relevant bitmap page is protected by a raised barrier before any state transition occurs. This closes the race window where the state machine could complete without the barrier being in place.
Preconditions
- configThe MD device must be using the lockless bitmap (md-llbitmap) feature introduced by commit 5ab829f1971d.
- inputThe attacker must be able to trigger concurrent write or discard I/O operations on overlapping bitmap regions.
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.