From: Jiale Yao The configuration stores check whether the device is powered before parsing the new value, then take the mutex again to update the field. A concurrent power-on can complete between these lock acquisitions, allowing a live device configuration to be changed. Parse the input before taking the mutex, then check powered and update the configuration while holding the same lock. Fixes: d969d504bc13 ("rnull: enable configuration via `configfs`") Signed-off-by: Jiale Yao --- drivers/block/rnull/configfs.rs | 42 ++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/drivers/block/rnull/configfs.rs b/drivers/block/rnull/configfs.rs index 32c10c3f4d0f..1808fcacfd55 100644 --- a/drivers/block/rnull/configfs.rs +++ b/drivers/block/rnull/configfs.rs @@ -174,15 +174,17 @@ impl configfs::AttributeOperations<1> for DeviceConfig { } fn store(this: &DeviceConfig, page: &[u8]) -> Result { - if this.data.lock().powered { - return Err(EBUSY); - } - let text = core::str::from_utf8(page)?.trim(); let value = text.parse::().map_err(|_| EINVAL)?; GenDiskBuilder::validate_block_size(value)?; - this.data.lock().block_size = value; + let mut guard = this.data.lock(); + + if guard.powered { + return Err(EBUSY); + } + + guard.block_size = value; Ok(()) } } @@ -204,11 +206,14 @@ impl configfs::AttributeOperations<2> for DeviceConfig { } fn store(this: &DeviceConfig, page: &[u8]) -> Result { - if this.data.lock().powered { + let value = kstrtobool_bytes(page)?; + let mut guard = this.data.lock(); + + if guard.powered { return Err(EBUSY); } - this.data.lock().rotational = kstrtobool_bytes(page)?; + guard.rotational = value; Ok(()) } @@ -225,14 +230,15 @@ impl configfs::AttributeOperations<3> for DeviceConfig { } fn store(this: &DeviceConfig, page: &[u8]) -> Result { - if this.data.lock().powered { - return Err(EBUSY); - } - let text = core::str::from_utf8(page)?.trim(); let value = text.parse::().map_err(|_| EINVAL)?; + let mut guard = this.data.lock(); - this.data.lock().capacity_mib = value; + if guard.powered { + return Err(EBUSY); + } + + guard.capacity_mib = value; Ok(()) } } @@ -248,14 +254,16 @@ impl configfs::AttributeOperations<4> for DeviceConfig { } fn store(this: &DeviceConfig, page: &[u8]) -> Result { - if this.data.lock().powered { - return Err(EBUSY); - } - let text = core::str::from_utf8(page)?.trim(); let value = text.parse::().map_err(|_| EINVAL)?; + let value = IRQMode::try_from(value)?; + let mut guard = this.data.lock(); + + if guard.powered { + return Err(EBUSY); + } - this.data.lock().irq_mode = IRQMode::try_from(value)?; + guard.irq_mode = value; Ok(()) } } -- 2.34.1