[PATCH v2] md/raid1: reject out-of-range raid_disks in setup_conf()

From: Gowtham S Bhushan

Date: Fri Oct 30 2026 - 00:40:25 EST


mddev->raid_disks can be set from user space with SET_ARRAY_INFO and
is not bounded before RUN_ARRAY reaches raid1_run(). With a very large
value, setup_conf() asks the allocator for more than KMALLOC_MAX_SIZE
when allocating conf->mirrors, and the allocator warns:

WARNING: mm/slub.c:5459 at ___kmalloc_large_node
setup_conf+0x15d/0x700
raid1_run+0x109/0x250
md_run+0x6c3/0xec0
do_md_run+0x27/0x3b0
md_ioctl+0x163f/0x1ca0

The array fails to start, but machines running with panic_on_warn
crash and syzbot keeps reporting it.

Fail early instead. Version 1.x metadata can describe at most 1920
devices, so use that as the upper bound, and test the sign before the
value is used. At that limit the allocations that scale with
raid_disks (conf->mirrors, the r1bio mempool element and the resync
buffers) stay well below KMALLOC_MAX_SIZE.

Reported-by: syzbot+75f49ec552cc74d9d69b@xxxxxxxxxxxxxxxxxxxxxxxxx
Closes: https://syzkaller.appspot.com/bug?extid=75f49ec552cc74d9d69b
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")

Signed-off-by: Gowtham S Bhushan <gowtham398gs@xxxxxxxxx>
---
drivers/md/raid1.c | 12 ++++++++++++
1 file changed, 12 insertions(+)

diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index f0646fb24371..1cfe983167de 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -48,6 +48,13 @@ static void allow_barrier(struct r1conf *conf, sector_t sector_nr);
static void lower_barrier(struct r1conf *conf, sector_t sector_nr);
static void raid1_free(struct mddev *mddev, void *priv);

+/*
+ * Version 1.x md metadata keeps a 256-byte header and then 2 bytes per
+ * device in a 4096-byte block, so no array described by it can have more
+ * devices than this. Arrays created through the ioctl alone have no
+ * on-disk limit, so apply the same cap to them.
+ */
+#define RAID1_MAX_DISKS ((4096 - 256) / 2)
#define RAID_1_10_NAME "raid1"
#include "raid1-10.c"

@@ -3051,6 +3058,11 @@ static struct r1conf *setup_conf(struct mddev *mddev)
size_t r1bio_size;
int err = -ENOMEM;

+ /* raid_disks comes from user space and sizes the allocations below */
+
+ if (mddev->raid_disks <= 0 || mddev->raid_disks > RAID1_MAX_DISKS)
+ return ERR_PTR(-EINVAL);
+
conf = kzalloc_obj(struct r1conf);
if (!conf)
goto abort;
--
2.56.0