CVE-2026-46327
Description
In the Linux kernel, the following vulnerability has been resolved:
dm: fix unlocked test for dm_suspended_md
The function dm_blk_report_zones tests if the device is suspended with the "dm_suspended_md" call. However, this function is called without holding any locks, so the device may be suspended just after it.
Move the call to dm_suspended_md after dm_get_live_table, so that the device can't be suspended after the suspended state was tested.
Affected products
1Patches
8d809a36692eedm: fix unlocked test for dm_suspended_md
1 file changed · +6 −4
drivers/md/dm-zone.c+6 −4 modifieddiff --git a/drivers/md/dm-zone.c b/drivers/md/dm-zone.c index c95e417194b33..bc4e45862a220 100644 --- a/drivers/md/dm-zone.c +++ b/drivers/md/dm-zone.c @@ -60,11 +60,13 @@ int dm_blk_report_zones(struct gendisk *disk, sector_t sector, * Zone revalidation during __bind() is in progress, but this * call is from a different process */ - if (dm_suspended_md(md)) - return -EAGAIN; - map = dm_get_live_table(md, &srcu_idx); put_table = true; + + if (dm_suspended_md(md)) { + ret = -EAGAIN; + goto do_put_table; + } } else { /* Zone revalidation during __bind() */ map = zone_revalidate_map; @@ -79,6 +81,7 @@ int dm_blk_report_zones(struct gendisk *disk, sector_t sector, ret = dm_blk_do_report_zones(md, map, nr_zones, &dm_args); } +do_put_table: if (put_table) dm_put_live_table(md, srcu_idx); -- cgit 1.3-korg
175ac0a61154dm: fix unlocked test for dm_suspended_md
1 file changed · +6 −4
drivers/md/dm-zone.c+6 −4 modifieddiff --git a/drivers/md/dm-zone.c b/drivers/md/dm-zone.c index 04cc36a9d5ca4..d7b1c89fcd87b 100644 --- a/drivers/md/dm-zone.c +++ b/drivers/md/dm-zone.c @@ -66,11 +66,13 @@ int dm_blk_report_zones(struct gendisk *disk, sector_t sector, * Zone revalidation during __bind() is in progress, but this * call is from a different process */ - if (dm_suspended_md(md)) - return -EAGAIN; - map = dm_get_live_table(md, &srcu_idx); put_table = true; + + if (dm_suspended_md(md)) { + ret = -EAGAIN; + goto do_put_table; + } } else { /* Zone revalidation during __bind() */ map = zone_revalidate_map; @@ -80,6 +82,7 @@ int dm_blk_report_zones(struct gendisk *disk, sector_t sector, ret = dm_blk_do_report_zones(md, map, sector, nr_zones, cb, data); +do_put_table: if (put_table) dm_put_live_table(md, srcu_idx); -- cgit 1.3-korg
7a3385e97af2dm: fix unlocked test for dm_suspended_md
1 file changed · +6 −4
drivers/md/dm-zone.c+6 −4 modifieddiff --git a/drivers/md/dm-zone.c b/drivers/md/dm-zone.c index 78e17dd4d01b8..ba39c8313f32b 100644 --- a/drivers/md/dm-zone.c +++ b/drivers/md/dm-zone.c @@ -66,11 +66,13 @@ int dm_blk_report_zones(struct gendisk *disk, sector_t sector, * Zone revalidation during __bind() is in progress, but this * call is from a different process */ - if (dm_suspended_md(md)) - return -EAGAIN; - map = dm_get_live_table(md, &srcu_idx); put_table = true; + + if (dm_suspended_md(md)) { + ret = -EAGAIN; + goto do_put_table; + } } else { /* Zone revalidation during __bind() */ map = zone_revalidate_map; @@ -80,6 +82,7 @@ int dm_blk_report_zones(struct gendisk *disk, sector_t sector, ret = dm_blk_do_report_zones(md, map, sector, nr_zones, cb, data); +do_put_table: if (put_table) dm_put_live_table(md, srcu_idx); -- cgit 1.3-korg
24c405fdbe21dm: fix unlocked test for dm_suspended_md
1 file changed · +6 −4
drivers/md/dm-zone.c+6 −4 modifieddiff --git a/drivers/md/dm-zone.c b/drivers/md/dm-zone.c index c95e417194b33..bc4e45862a220 100644 --- a/drivers/md/dm-zone.c +++ b/drivers/md/dm-zone.c @@ -60,11 +60,13 @@ int dm_blk_report_zones(struct gendisk *disk, sector_t sector, * Zone revalidation during __bind() is in progress, but this * call is from a different process */ - if (dm_suspended_md(md)) - return -EAGAIN; - map = dm_get_live_table(md, &srcu_idx); put_table = true; + + if (dm_suspended_md(md)) { + ret = -EAGAIN; + goto do_put_table; + } } else { /* Zone revalidation during __bind() */ map = zone_revalidate_map; @@ -79,6 +81,7 @@ int dm_blk_report_zones(struct gendisk *disk, sector_t sector, ret = dm_blk_do_report_zones(md, map, nr_zones, &dm_args); } +do_put_table: if (put_table) dm_put_live_table(md, srcu_idx); -- cgit 1.3-korg
175ac0a61154dm: fix unlocked test for dm_suspended_md
1 file changed · +6 −4
drivers/md/dm-zone.c+6 −4 modifieddiff --git a/drivers/md/dm-zone.c b/drivers/md/dm-zone.c index 04cc36a9d5ca4..d7b1c89fcd87b 100644 --- a/drivers/md/dm-zone.c +++ b/drivers/md/dm-zone.c @@ -66,11 +66,13 @@ int dm_blk_report_zones(struct gendisk *disk, sector_t sector, * Zone revalidation during __bind() is in progress, but this * call is from a different process */ - if (dm_suspended_md(md)) - return -EAGAIN; - map = dm_get_live_table(md, &srcu_idx); put_table = true; + + if (dm_suspended_md(md)) { + ret = -EAGAIN; + goto do_put_table; + } } else { /* Zone revalidation during __bind() */ map = zone_revalidate_map; @@ -80,6 +82,7 @@ int dm_blk_report_zones(struct gendisk *disk, sector_t sector, ret = dm_blk_do_report_zones(md, map, sector, nr_zones, cb, data); +do_put_table: if (put_table) dm_put_live_table(md, srcu_idx); -- cgit 1.3-korg
24c405fdbe21dm: fix unlocked test for dm_suspended_md
1 file changed · +6 −4
drivers/md/dm-zone.c+6 −4 modifieddiff --git a/drivers/md/dm-zone.c b/drivers/md/dm-zone.c index c95e417194b33..bc4e45862a220 100644 --- a/drivers/md/dm-zone.c +++ b/drivers/md/dm-zone.c @@ -60,11 +60,13 @@ int dm_blk_report_zones(struct gendisk *disk, sector_t sector, * Zone revalidation during __bind() is in progress, but this * call is from a different process */ - if (dm_suspended_md(md)) - return -EAGAIN; - map = dm_get_live_table(md, &srcu_idx); put_table = true; + + if (dm_suspended_md(md)) { + ret = -EAGAIN; + goto do_put_table; + } } else { /* Zone revalidation during __bind() */ map = zone_revalidate_map; @@ -79,6 +81,7 @@ int dm_blk_report_zones(struct gendisk *disk, sector_t sector, ret = dm_blk_do_report_zones(md, map, nr_zones, &dm_args); } +do_put_table: if (put_table) dm_put_live_table(md, srcu_idx); -- cgit 1.3-korg
7a3385e97af2dm: fix unlocked test for dm_suspended_md
1 file changed · +6 −4
drivers/md/dm-zone.c+6 −4 modifieddiff --git a/drivers/md/dm-zone.c b/drivers/md/dm-zone.c index 78e17dd4d01b8..ba39c8313f32b 100644 --- a/drivers/md/dm-zone.c +++ b/drivers/md/dm-zone.c @@ -66,11 +66,13 @@ int dm_blk_report_zones(struct gendisk *disk, sector_t sector, * Zone revalidation during __bind() is in progress, but this * call is from a different process */ - if (dm_suspended_md(md)) - return -EAGAIN; - map = dm_get_live_table(md, &srcu_idx); put_table = true; + + if (dm_suspended_md(md)) { + ret = -EAGAIN; + goto do_put_table; + } } else { /* Zone revalidation during __bind() */ map = zone_revalidate_map; @@ -80,6 +82,7 @@ int dm_blk_report_zones(struct gendisk *disk, sector_t sector, ret = dm_blk_do_report_zones(md, map, sector, nr_zones, cb, data); +do_put_table: if (put_table) dm_put_live_table(md, srcu_idx); -- cgit 1.3-korg
d809a36692eedm: fix unlocked test for dm_suspended_md
1 file changed · +6 −4
drivers/md/dm-zone.c+6 −4 modifieddiff --git a/drivers/md/dm-zone.c b/drivers/md/dm-zone.c index c95e417194b33..bc4e45862a220 100644 --- a/drivers/md/dm-zone.c +++ b/drivers/md/dm-zone.c @@ -60,11 +60,13 @@ int dm_blk_report_zones(struct gendisk *disk, sector_t sector, * Zone revalidation during __bind() is in progress, but this * call is from a different process */ - if (dm_suspended_md(md)) - return -EAGAIN; - map = dm_get_live_table(md, &srcu_idx); put_table = true; + + if (dm_suspended_md(md)) { + ret = -EAGAIN; + goto do_put_table; + } } else { /* Zone revalidation during __bind() */ map = zone_revalidate_map; @@ -79,6 +81,7 @@ int dm_blk_report_zones(struct gendisk *disk, sector_t sector, ret = dm_blk_do_report_zones(md, map, nr_zones, &dm_args); } +do_put_table: if (put_table) dm_put_live_table(md, srcu_idx); -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"The dm_blk_report_zones function checks if a device is suspended without holding necessary locks, allowing the device to be suspended between the check and subsequent operations."
Attack vector
An attacker can trigger this vulnerability by calling the dm_blk_report_zones function. The vulnerability occurs because the check for the device's suspended state, using dm_suspended_md, is performed without acquiring any locks. This allows a race condition where the device can be suspended by another process immediately after the check but before the device's live table is obtained.
Affected code
The vulnerability resides in the dm_blk_report_zones function within the drivers/md/dm-zone.c file. Specifically, the check for the device's suspended state using dm_suspended_md was performed before acquiring the necessary locks to access the device's table.
What the fix does
The patch moves the call to dm_suspended_md to occur after dm_get_live_table has been called and the lock has been acquired [patch_id=5357581]. This ensures that the device cannot be suspended between the check for its suspended state and the retrieval of its live table, thus preventing the race condition.
Generated on Jun 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4News mentions
1- Linux Kernel: 25 Vulnerabilities Disclosed in Single Batch on June 8-9, 2026Vypr Intelligence · Jun 9, 2026