summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYu Kuai <yukuai@fygo.io>2026-08-03 03:50:13 +0800
committerYu Kuai <yukuai@fygo.io>2026-08-07 14:43:33 +0800
commita41bb2ee1aca486853e84920565e50c15f86fa5d (patch)
treed5f68da2d2d3593a54cdc73d7ae103f971f3f453
parentdbd21b489ac1afda73de401a446ecad2b53f413c (diff)
downloadlinux-a41bb2ee1aca486853e84920565e50c15f86fa5d.tar.gz
linux-a41bb2ee1aca486853e84920565e50c15f86fa5d.zip
md/raid5: reject zero-sector reshape chunks
Sashiko reported that RAID5 can accept a reshape chunk size that becomes zero sectors. chunk_size_store() stores the sysfs byte value as n >> 9, so writing a value below 512 bytes sets mddev->new_chunk_sectors to zero. RAID5 then accepted that pending reshape geometry and raid5_start_reshape() installed it into conf->chunk_sectors, letting reshape code divide by zero. Reject zero-sector chunks both in check_reshape(), where normal sysfs requests are validated, and in raid5_start_reshape(), so assembly/resume paths also cannot install zero chunk geometry. Test script: in QEMU, create a plain three-disk RAID5 array with 64K chunks, write/read back a small pattern, write 1 to /sys/block/md0/md/chunk_size, add a fourth disk, and run mdadm --grow --raid-devices=4 --backup-file=... . The script scans dmesg for divide error/Oops/KASAN signatures. Bad kernel, eb29914412c3: echo 1 > /sys/block/md0/md/chunk_size mdadm --grow /dev/md0 --raid-devices=4 --backup-file=/root/md0-grow.bak Oops: divide error: 0000 [#1] SMP KASAN NOPTI RIP: raid5_get_active_stripe+0x863/0xc10 Call Trace: raid5_sync_request md_do_sync md_thread Kernel panic - not syncing: Fatal exception Fixed kernel: echo 1 > /sys/block/md0/md/chunk_size bash: echo: write error: Invalid argument chunk_write_rc=1 grow_rc=skipped RESULT: REJECTED_ZERO_CHUNK_NO_OOPS Tested-by: Mykola Marzhan <mykola@meshstor.io> Link: https://patch.msgid.link/20260802195038.164272-5-yukuai@kernel.org Signed-off-by: Yu Kuai <yukuai@fygo.io>
-rw-r--r--drivers/md/raid5.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index e2c5a7072aca..d128d238e1da 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -8548,6 +8548,8 @@ static int check_reshape(struct mddev *mddev)
return 0; /* nothing to do */
if (has_failed(conf))
return -EINVAL;
+ if (!mddev->new_chunk_sectors)
+ return -EINVAL;
if (mddev->delta_disks < 0 && mddev->reshape_position == MaxSector) {
/* We might be able to shrink, but the devices must
* be made bigger first.
@@ -8591,6 +8593,9 @@ static int raid5_start_reshape(struct mddev *mddev)
if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
return -EBUSY;
+ if (!mddev->new_chunk_sectors)
+ return -EINVAL;
+
if (!check_stripe_cache(mddev))
return -ENOSPC;