[PATCH] rnull: fix geometry store check-then-act across lock scopes

From: Qingxiao Xu

Date: Tue Sep 08 2026 - 16:31:49 EST


The blocksize/rotational/capacity/irqmode stores check powered under one
Mutex acquisition, drop the guard, then update under a second acquisition.
A concurrent power-on can create the live disk from stale geometry in
between, leaving powered==true with config != live disk.

Hold one guard for the powered check and the field update.

Signed-off-by: Qingxiao Xu <qingxiao@xxxxxxxx>
---
drivers/block/rnull/configfs.rs | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/block/rnull/configfs.rs b/drivers/block/rnull/configfs.rs
index 32c10c3f4..66ef91b3f 100644
--- a/drivers/block/rnull/configfs.rs
+++ b/drivers/block/rnull/configfs.rs
@@ -174,7 +174,8 @@ impl configfs::AttributeOperations<1> for DeviceConfig {
}

fn store(this: &DeviceConfig, page: &[u8]) -> Result {
- if this.data.lock().powered {
+ let mut guard = this.data.lock();
+ if guard.powered {
return Err(EBUSY);
}

@@ -182,7 +183,7 @@ fn store(this: &DeviceConfig, page: &[u8]) -> Result {
let value = text.parse::<u32>().map_err(|_| EINVAL)?;

GenDiskBuilder::validate_block_size(value)?;
- this.data.lock().block_size = value;
+ guard.block_size = value;
Ok(())
}
}
@@ -204,11 +205,12 @@ impl configfs::AttributeOperations<2> for DeviceConfig {
}

fn store(this: &DeviceConfig, page: &[u8]) -> Result {
- if this.data.lock().powered {
+ let mut guard = this.data.lock();
+ if guard.powered {
return Err(EBUSY);
}

- this.data.lock().rotational = kstrtobool_bytes(page)?;
+ guard.rotational = kstrtobool_bytes(page)?;

Ok(())
}
@@ -225,14 +227,15 @@ impl configfs::AttributeOperations<3> for DeviceConfig {
}

fn store(this: &DeviceConfig, page: &[u8]) -> Result {
- if this.data.lock().powered {
+ let mut guard = this.data.lock();
+ if guard.powered {
return Err(EBUSY);
}

let text = core::str::from_utf8(page)?.trim();
let value = text.parse::<u64>().map_err(|_| EINVAL)?;

- this.data.lock().capacity_mib = value;
+ guard.capacity_mib = value;
Ok(())
}
}
@@ -248,14 +251,15 @@ impl configfs::AttributeOperations<4> for DeviceConfig {
}

fn store(this: &DeviceConfig, page: &[u8]) -> Result {
- if this.data.lock().powered {
+ let mut guard = this.data.lock();
+ if guard.powered {
return Err(EBUSY);
}

let text = core::str::from_utf8(page)?.trim();
let value = text.parse::<u8>().map_err(|_| EINVAL)?;

- this.data.lock().irq_mode = IRQMode::try_from(value)?;
+ guard.irq_mode = IRQMode::try_from(value)?;
Ok(())
}
}
--
2.43.0