md/raid5: validate disk count before reshape assembly
v2 cover md/raid5: validate disk count before reshape assembly
From: Chen Cheng <[email protected]>
The previous patch rejects raid4/5 arrays with too few disks in setup_conf(). During reshape assembly, raid5_run() still divides by the data-disk count before that check, so a crafted superblock can hit division by zero.
Extract min_raid_disks() and reject invalid reshape geometries in raid5_run() first.
v1 -> v2:
- Added Link
Chen Cheng (2):
md/raid5: extract min_raid_disks()
md/raid5: reject invalid reshape disks in raid5_run()
drivers/md/raid5.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-)
Signature · 1 line
2.55.0
PATCH v2 1/2 md/raid5: extract min_raid_disks()
From: Chen Cheng <[email protected]>
Reuse the minimum disk count in setup_conf() and check_reshape().
--- drivers/md/raid5.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-)
drivers/md/raid5.c +11 -10
@@ -7630,14 +7630,19 @@ static unsigned long raid5_cache_count(struct shrinker *shrink,/* unlikely, but not impossible */ return 0 ;return max_stripes - min_stripes; } +static int min_raid_disks (int level) +{ +return level ==6 ?4 :2 ; +} +static struct r5conf *setup_conf (struct mddev *mddev) {struct r5conf *conf; -int raid_disk, memory, max_disks; +int raid_disk, memory, max_disks, min_disks;struct md_rdev *rdev;struct disk_info *disk;char pers_name[6 ];int i;int group_cnt;
@@ -7657,15 +7662,15 @@ static struct r5conf *setup_conf(struct mddev *mddev) && !algorithm_valid_raid6(mddev->new_layout))) {pr_warn ("md/raid:%s: layout %d not supported\n" ,mdname (mddev), mddev->new_layout);return ERR_PTR (-EIO ); } -if ((mddev->new_level !=6 && mddev->raid_disks <2 ) || - (mddev->new_level ==6 && mddev->raid_disks <4 )) { + min_disks =min_raid_disks (mddev->new_level); +if (mddev->raid_disks < min_disks) {pr_warn ("md/raid:%s: not enough configured devices (%d, minimum %d)\n" ,mdname (mddev), mddev->raid_disks, - mddev->new_level ==6 ?4 :2 ); + min_disks);return ERR_PTR (-EINVAL ); } if (!mddev->new_chunk_sectors || (mddev->new_chunk_sectors << 9) % PAGE_SIZE ||
@@ -8608,17 +8613,13 @@ static int check_reshape(struct mddev *mddev)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. -* For raid6, 4 is the minimum size. -* Otherwise 2 is the minimum */ -int min =2 ; -if (mddev->level ==6 ) - min =4 ; -if (mddev->raid_disks + mddev->delta_disks < min) +if (mddev->raid_disks + mddev->delta_disks < +min_raid_disks (mddev->level))return -EINVAL ; }if (!check_stripe_cache (mddev))return -ENOSPC ;
Signature · 1 line
2.55.0
PATCH v2 2/2 md/raid5: reject invalid reshape disks in raid5_run()
In reply to Chen ChengFrom: Chen Cheng <[email protected]>
Check disk count before dividing by data disks while assembling a reshape, otherwise too few disks can cause division by zero.
---
v1 -> v2:
- Added Link
--- drivers/md/raid5.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/md/raid5.c +7 -0
@@ -8053,10 +8053,11 @@ static int raid5_run(struct mddev *mddev)* the array in read-only mode, so we check for that. */ sector_t here_new, here_old;int old_disks;int max_degraded = (mddev->level ==6 ?2 :1 ); +int min_disks =min_raid_disks (mddev->level);int chunk_sectors;int new_data_disks;if (journal_dev) { pr_warn("md/raid:%s: don't support reshape with journal - aborting.\n",
@@ -8068,10 +8069,16 @@ static int raid5_run(struct mddev *mddev)pr_warn ("md/raid:%s: unsupported reshape required - aborting.\n" ,mdname (mddev));return -EINVAL ; } old_disks = mddev->raid_disks - mddev->delta_disks; +if (mddev->raid_disks < min_disks || old_disks < min_disks) { +pr_warn ("md/raid:%s: invalid reshape disks (%d -> %d, min %d)\n" , +mdname (mddev), old_disks, mddev->raid_disks, + min_disks); +return -EINVAL ; + }/* reshape_position must be on a new-stripe boundary, and one * further up in new geometry must map after here in old * geometry. * If the chunk sizes are different, then as we perform reshape * in units of the largest of the two, reshape_position needs
Signature · 1 line
2.55.0
Quoted 13 lines · Chen Cheng
From: Chen Cheng<[email protected]>
The previous patch rejects raid4/5 arrays with too few disks in
setup_conf(). During reshape assembly,raid5_run()still divides by the data-disk count before that check, so a crafted superblock can hit division by zero.Extract
min_raid_disks()and reject invalid reshape geometries inraid5_run()first.v1 -> v2:
- Added Link
Quoted 6 lines
Chen Cheng (2):
md/raid5: extractmin_raid_disks()
md/raid5: reject invalid reshape disks inraid5_run()drivers/md/raid5.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-)
Applied to md-7.4
Signature · 2 lines
Thanks, Kuai