VYPR
Unrated severityNVD Advisory· Published May 27, 2026· Updated May 27, 2026

CVE-2026-45953

CVE-2026-45953

Description

In the Linux kernel, the following vulnerability has been resolved:

md/raid5: fix IO hang with degraded array with llbitmap

When llbitmap bit state is still unwritten, any new write should force rcw, as bitmap_ops->blocks_synced() is checked in handle_stripe_dirtying(). However, later the same check is missing in need_this_block(), causing stripe to deadloop during handling because handle_stripe() will decide to go to handle_stripe_fill(), meanwhile need_this_block() always return 0 and nothing is handled.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

In the Linux kernel md/raid5, a missing check in need_this_block() when using llbitmap with degraded arrays causes IO hang due to stripe deadloop.

Vulnerability

The vulnerability exists in the Linux kernel's md/raid5 module when using an llbitmap (log-likelihood bitmap). When a bitmap bit state is unwritten, the function handle_stripe_dirtying() correctly checks bitmap_ops->blocks_synced() to force an RCW (read-change-write) path. However, the same check is missing in need_this_block(), leading to a deadloop in stripe handling. handle_stripe() decides to proceed to handle_stripe_fill(), but need_this_block() always returns 0, causing no progress and an IO hang on degraded arrays. Affected versions are all Linux kernel versions before the fix commit [1].

Exploitation

An attacker must be able to write to a degraded RAID5 array that uses an llbitmap, with a bitmap bit state that is unwritten. No special privileges are required beyond normal write access. The attack sequence involves initiating a write operation to a stripe that has an unwritten bitmap bit while the array is degraded. This triggers the deadloop, resulting in an indefinite hang of I/O operations to that array.

Impact

Successful exploitation leads to an IO hang on the degraded RAID5 array, causing a denial of service (DoS) on the system. The system may become unresponsive as I/O operations stall indefinitely. This affects data availability and can disrupt system operation.

Mitigation

The issue is fixed by the Linux kernel commit [1] (commit hash cd1635d844d26471c56c0a432abdee12fc9ad735). Users should update their kernel to a version that includes this patch. No workarounds are mentioned in the available references. The CVE is not listed on the CISA Known Exploited Vulnerabilities (KEV) catalog.

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

1

Patches

6
870b9f15867b

md/raid5: fix IO hang with degraded array with llbitmap

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitYu KuaiJan 23, 2026Fixed in 6.18.14via kernel-cna
2 files changed · +12 4
  • drivers/md/raid5.c+6 2 modified
    diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
    index 1041788a54c20c..3b711a1198adbe 100644
    --- a/drivers/md/raid5.c
    +++ b/drivers/md/raid5.c
    @@ -3751,9 +3751,14 @@ static int need_this_block(struct stripe_head *sh, struct stripe_head_state *s,
     	struct r5dev *dev = &sh->dev[disk_idx];
     	struct r5dev *fdev[2] = { &sh->dev[s->failed_num[0]],
     				  &sh->dev[s->failed_num[1]] };
    +	struct mddev *mddev = sh->raid_conf->mddev;
    +	bool force_rcw = false;
     	int i;
    -	bool force_rcw = (sh->raid_conf->rmw_level == PARITY_DISABLE_RMW);
     
    +	if (sh->raid_conf->rmw_level == PARITY_DISABLE_RMW ||
    +	    (mddev->bitmap_ops && mddev->bitmap_ops->blocks_synced &&
    +	     !mddev->bitmap_ops->blocks_synced(mddev, sh->sector)))
    +		force_rcw = true;
     
     	if (test_bit(R5_LOCKED, &dev->flags) ||
     	    test_bit(R5_UPTODATE, &dev->flags))
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/md/raid5.c+6 2 modified
    diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
    index 1041788a54c20c..3b711a1198adbe 100644
    --- a/drivers/md/raid5.c
    +++ b/drivers/md/raid5.c
    @@ -3751,9 +3751,14 @@ static int need_this_block(struct stripe_head *sh, struct stripe_head_state *s,
     	struct r5dev *dev = &sh->dev[disk_idx];
     	struct r5dev *fdev[2] = { &sh->dev[s->failed_num[0]],
     				  &sh->dev[s->failed_num[1]] };
    +	struct mddev *mddev = sh->raid_conf->mddev;
    +	bool force_rcw = false;
     	int i;
    -	bool force_rcw = (sh->raid_conf->rmw_level == PARITY_DISABLE_RMW);
     
    +	if (sh->raid_conf->rmw_level == PARITY_DISABLE_RMW ||
    +	    (mddev->bitmap_ops && mddev->bitmap_ops->blocks_synced &&
    +	     !mddev->bitmap_ops->blocks_synced(mddev, sh->sector)))
    +		force_rcw = true;
     
     	if (test_bit(R5_LOCKED, &dev->flags) ||
     	    test_bit(R5_UPTODATE, &dev->flags))
    -- 
    cgit 1.3-korg
    
    
    
28ef299e7a5b

md/raid5: fix IO hang with degraded array with llbitmap

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitYu KuaiJan 23, 2026Fixed in 6.19.4via kernel-cna
2 files changed · +12 4
  • drivers/md/raid5.c+6 2 modified
    diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
    index a85878b009f9a4..bdf248db1330ae 100644
    --- a/drivers/md/raid5.c
    +++ b/drivers/md/raid5.c
    @@ -3751,9 +3751,14 @@ static int need_this_block(struct stripe_head *sh, struct stripe_head_state *s,
     	struct r5dev *dev = &sh->dev[disk_idx];
     	struct r5dev *fdev[2] = { &sh->dev[s->failed_num[0]],
     				  &sh->dev[s->failed_num[1]] };
    +	struct mddev *mddev = sh->raid_conf->mddev;
    +	bool force_rcw = false;
     	int i;
    -	bool force_rcw = (sh->raid_conf->rmw_level == PARITY_DISABLE_RMW);
     
    +	if (sh->raid_conf->rmw_level == PARITY_DISABLE_RMW ||
    +	    (mddev->bitmap_ops && mddev->bitmap_ops->blocks_synced &&
    +	     !mddev->bitmap_ops->blocks_synced(mddev, sh->sector)))
    +		force_rcw = true;
     
     	if (test_bit(R5_LOCKED, &dev->flags) ||
     	    test_bit(R5_UPTODATE, &dev->flags))
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/md/raid5.c+6 2 modified
    diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
    index a85878b009f9a4..bdf248db1330ae 100644
    --- a/drivers/md/raid5.c
    +++ b/drivers/md/raid5.c
    @@ -3751,9 +3751,14 @@ static int need_this_block(struct stripe_head *sh, struct stripe_head_state *s,
     	struct r5dev *dev = &sh->dev[disk_idx];
     	struct r5dev *fdev[2] = { &sh->dev[s->failed_num[0]],
     				  &sh->dev[s->failed_num[1]] };
    +	struct mddev *mddev = sh->raid_conf->mddev;
    +	bool force_rcw = false;
     	int i;
    -	bool force_rcw = (sh->raid_conf->rmw_level == PARITY_DISABLE_RMW);
     
    +	if (sh->raid_conf->rmw_level == PARITY_DISABLE_RMW ||
    +	    (mddev->bitmap_ops && mddev->bitmap_ops->blocks_synced &&
    +	     !mddev->bitmap_ops->blocks_synced(mddev, sh->sector)))
    +		force_rcw = true;
     
     	if (test_bit(R5_LOCKED, &dev->flags) ||
     	    test_bit(R5_UPTODATE, &dev->flags))
    -- 
    cgit 1.3-korg
    
    
    
cd1635d844d2

md/raid5: fix IO hang with degraded array with llbitmap

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitYu KuaiJan 23, 2026Fixed in 7.0via kernel-cna
2 files changed · +12 4
  • drivers/md/raid5.c+6 2 modified
    diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
    index 6d408aaaacf37a..8854e024f3113b 100644
    --- a/drivers/md/raid5.c
    +++ b/drivers/md/raid5.c
    @@ -3751,9 +3751,14 @@ static int need_this_block(struct stripe_head *sh, struct stripe_head_state *s,
     	struct r5dev *dev = &sh->dev[disk_idx];
     	struct r5dev *fdev[2] = { &sh->dev[s->failed_num[0]],
     				  &sh->dev[s->failed_num[1]] };
    +	struct mddev *mddev = sh->raid_conf->mddev;
    +	bool force_rcw = false;
     	int i;
    -	bool force_rcw = (sh->raid_conf->rmw_level == PARITY_DISABLE_RMW);
     
    +	if (sh->raid_conf->rmw_level == PARITY_DISABLE_RMW ||
    +	    (mddev->bitmap_ops && mddev->bitmap_ops->blocks_synced &&
    +	     !mddev->bitmap_ops->blocks_synced(mddev, sh->sector)))
    +		force_rcw = true;
     
     	if (test_bit(R5_LOCKED, &dev->flags) ||
     	    test_bit(R5_UPTODATE, &dev->flags))
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/md/raid5.c+6 2 modified
    diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
    index 6d408aaaacf37a..8854e024f3113b 100644
    --- a/drivers/md/raid5.c
    +++ b/drivers/md/raid5.c
    @@ -3751,9 +3751,14 @@ static int need_this_block(struct stripe_head *sh, struct stripe_head_state *s,
     	struct r5dev *dev = &sh->dev[disk_idx];
     	struct r5dev *fdev[2] = { &sh->dev[s->failed_num[0]],
     				  &sh->dev[s->failed_num[1]] };
    +	struct mddev *mddev = sh->raid_conf->mddev;
    +	bool force_rcw = false;
     	int i;
    -	bool force_rcw = (sh->raid_conf->rmw_level == PARITY_DISABLE_RMW);
     
    +	if (sh->raid_conf->rmw_level == PARITY_DISABLE_RMW ||
    +	    (mddev->bitmap_ops && mddev->bitmap_ops->blocks_synced &&
    +	     !mddev->bitmap_ops->blocks_synced(mddev, sh->sector)))
    +		force_rcw = true;
     
     	if (test_bit(R5_LOCKED, &dev->flags) ||
     	    test_bit(R5_UPTODATE, &dev->flags))
    -- 
    cgit 1.3-korg
    
    
    
cd1635d844d2

md/raid5: fix IO hang with degraded array with llbitmap

2 files changed · +12 4
  • drivers/md/raid5.c+6 2 modified
    diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
    index 6d408aaaacf37a..8854e024f3113b 100644
    --- a/drivers/md/raid5.c
    +++ b/drivers/md/raid5.c
    @@ -3751,9 +3751,14 @@ static int need_this_block(struct stripe_head *sh, struct stripe_head_state *s,
     	struct r5dev *dev = &sh->dev[disk_idx];
     	struct r5dev *fdev[2] = { &sh->dev[s->failed_num[0]],
     				  &sh->dev[s->failed_num[1]] };
    +	struct mddev *mddev = sh->raid_conf->mddev;
    +	bool force_rcw = false;
     	int i;
    -	bool force_rcw = (sh->raid_conf->rmw_level == PARITY_DISABLE_RMW);
     
    +	if (sh->raid_conf->rmw_level == PARITY_DISABLE_RMW ||
    +	    (mddev->bitmap_ops && mddev->bitmap_ops->blocks_synced &&
    +	     !mddev->bitmap_ops->blocks_synced(mddev, sh->sector)))
    +		force_rcw = true;
     
     	if (test_bit(R5_LOCKED, &dev->flags) ||
     	    test_bit(R5_UPTODATE, &dev->flags))
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/md/raid5.c+6 2 modified
    diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
    index 6d408aaaacf37a..8854e024f3113b 100644
    --- a/drivers/md/raid5.c
    +++ b/drivers/md/raid5.c
    @@ -3751,9 +3751,14 @@ static int need_this_block(struct stripe_head *sh, struct stripe_head_state *s,
     	struct r5dev *dev = &sh->dev[disk_idx];
     	struct r5dev *fdev[2] = { &sh->dev[s->failed_num[0]],
     				  &sh->dev[s->failed_num[1]] };
    +	struct mddev *mddev = sh->raid_conf->mddev;
    +	bool force_rcw = false;
     	int i;
    -	bool force_rcw = (sh->raid_conf->rmw_level == PARITY_DISABLE_RMW);
     
    +	if (sh->raid_conf->rmw_level == PARITY_DISABLE_RMW ||
    +	    (mddev->bitmap_ops && mddev->bitmap_ops->blocks_synced &&
    +	     !mddev->bitmap_ops->blocks_synced(mddev, sh->sector)))
    +		force_rcw = true;
     
     	if (test_bit(R5_LOCKED, &dev->flags) ||
     	    test_bit(R5_UPTODATE, &dev->flags))
    -- 
    cgit 1.3-korg
    
    
    
28ef299e7a5b

md/raid5: fix IO hang with degraded array with llbitmap

2 files changed · +12 4
  • drivers/md/raid5.c+6 2 modified
    diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
    index a85878b009f9a4..bdf248db1330ae 100644
    --- a/drivers/md/raid5.c
    +++ b/drivers/md/raid5.c
    @@ -3751,9 +3751,14 @@ static int need_this_block(struct stripe_head *sh, struct stripe_head_state *s,
     	struct r5dev *dev = &sh->dev[disk_idx];
     	struct r5dev *fdev[2] = { &sh->dev[s->failed_num[0]],
     				  &sh->dev[s->failed_num[1]] };
    +	struct mddev *mddev = sh->raid_conf->mddev;
    +	bool force_rcw = false;
     	int i;
    -	bool force_rcw = (sh->raid_conf->rmw_level == PARITY_DISABLE_RMW);
     
    +	if (sh->raid_conf->rmw_level == PARITY_DISABLE_RMW ||
    +	    (mddev->bitmap_ops && mddev->bitmap_ops->blocks_synced &&
    +	     !mddev->bitmap_ops->blocks_synced(mddev, sh->sector)))
    +		force_rcw = true;
     
     	if (test_bit(R5_LOCKED, &dev->flags) ||
     	    test_bit(R5_UPTODATE, &dev->flags))
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/md/raid5.c+6 2 modified
    diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
    index a85878b009f9a4..bdf248db1330ae 100644
    --- a/drivers/md/raid5.c
    +++ b/drivers/md/raid5.c
    @@ -3751,9 +3751,14 @@ static int need_this_block(struct stripe_head *sh, struct stripe_head_state *s,
     	struct r5dev *dev = &sh->dev[disk_idx];
     	struct r5dev *fdev[2] = { &sh->dev[s->failed_num[0]],
     				  &sh->dev[s->failed_num[1]] };
    +	struct mddev *mddev = sh->raid_conf->mddev;
    +	bool force_rcw = false;
     	int i;
    -	bool force_rcw = (sh->raid_conf->rmw_level == PARITY_DISABLE_RMW);
     
    +	if (sh->raid_conf->rmw_level == PARITY_DISABLE_RMW ||
    +	    (mddev->bitmap_ops && mddev->bitmap_ops->blocks_synced &&
    +	     !mddev->bitmap_ops->blocks_synced(mddev, sh->sector)))
    +		force_rcw = true;
     
     	if (test_bit(R5_LOCKED, &dev->flags) ||
     	    test_bit(R5_UPTODATE, &dev->flags))
    -- 
    cgit 1.3-korg
    
    
    
870b9f15867b

md/raid5: fix IO hang with degraded array with llbitmap

2 files changed · +12 4
  • drivers/md/raid5.c+6 2 modified
    diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
    index 1041788a54c20c..3b711a1198adbe 100644
    --- a/drivers/md/raid5.c
    +++ b/drivers/md/raid5.c
    @@ -3751,9 +3751,14 @@ static int need_this_block(struct stripe_head *sh, struct stripe_head_state *s,
     	struct r5dev *dev = &sh->dev[disk_idx];
     	struct r5dev *fdev[2] = { &sh->dev[s->failed_num[0]],
     				  &sh->dev[s->failed_num[1]] };
    +	struct mddev *mddev = sh->raid_conf->mddev;
    +	bool force_rcw = false;
     	int i;
    -	bool force_rcw = (sh->raid_conf->rmw_level == PARITY_DISABLE_RMW);
     
    +	if (sh->raid_conf->rmw_level == PARITY_DISABLE_RMW ||
    +	    (mddev->bitmap_ops && mddev->bitmap_ops->blocks_synced &&
    +	     !mddev->bitmap_ops->blocks_synced(mddev, sh->sector)))
    +		force_rcw = true;
     
     	if (test_bit(R5_LOCKED, &dev->flags) ||
     	    test_bit(R5_UPTODATE, &dev->flags))
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/md/raid5.c+6 2 modified
    diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
    index 1041788a54c20c..3b711a1198adbe 100644
    --- a/drivers/md/raid5.c
    +++ b/drivers/md/raid5.c
    @@ -3751,9 +3751,14 @@ static int need_this_block(struct stripe_head *sh, struct stripe_head_state *s,
     	struct r5dev *dev = &sh->dev[disk_idx];
     	struct r5dev *fdev[2] = { &sh->dev[s->failed_num[0]],
     				  &sh->dev[s->failed_num[1]] };
    +	struct mddev *mddev = sh->raid_conf->mddev;
    +	bool force_rcw = false;
     	int i;
    -	bool force_rcw = (sh->raid_conf->rmw_level == PARITY_DISABLE_RMW);
     
    +	if (sh->raid_conf->rmw_level == PARITY_DISABLE_RMW ||
    +	    (mddev->bitmap_ops && mddev->bitmap_ops->blocks_synced &&
    +	     !mddev->bitmap_ops->blocks_synced(mddev, sh->sector)))
    +		force_rcw = true;
     
     	if (test_bit(R5_LOCKED, &dev->flags) ||
     	    test_bit(R5_UPTODATE, &dev->flags))
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Missing check for llbitmap blocks_synced() in need_this_block() causes the function to always return 0 when the bitmap bit is unwritten, leading to a stripe deadloop."

Attack vector

An attacker with write access to a degraded RAID5 array that uses the llbitmap (lockless bitmap) can trigger an IO hang. When the llbitmap bit for a stripe is still in the "unwritten" state, any new write to that stripe should force a reconstruct-write (RCW) path. The check for bitmap_ops->blocks_synced() exists in handle_stripe_dirtying() but is missing in need_this_block() [patch_id=2661043]. This causes handle_stripe() to route to handle_stripe_fill(), while need_this_block() always returns 0, so no blocks are processed and the stripe deadloops indefinitely.

Affected code

The bug is in the need_this_block() function in drivers/md/raid5.c [patch_id=2661043]. The function previously only set force_rcw based on sh->raid_conf->rmw_level == PARITY_DISABLE_RMW, missing the llbitmap unwritten state check that was already present in handle_stripe_dirtying().

What the fix does

The patch adds the same bitmap_ops->blocks_synced() check that already exists in handle_stripe_dirtying() into need_this_block() [patch_id=2661043]. Specifically, it expands the force_rcw condition from only checking PARITY_DISABLE_RMW to also checking whether mddev->bitmap_ops->blocks_synced() returns false (meaning the bitmap bit is unwritten). When force_rcw is true, need_this_block() returns 1 for the block, allowing the stripe to make progress instead of deadlooping.

Preconditions

  • configRAID5 array must be in degraded state (at least one failed disk)
  • configArray must use the llbitmap (lockless bitmap) feature
  • inputThe llbitmap bit for the target stripe must be in the unwritten state
  • inputA write I/O must be issued to the affected stripe

Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

3

News mentions

0

No linked articles in our index yet.