From nobody Thu Sep 24 13:41:51 2026 Received: from mail-wr1-f50.google.com (mail-wr1-f50.google.com [209.85.221.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 99D663AB269 for ; Wed, 23 Sep 2026 16:17:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790180255; cv=none; b=LuyNmHWiQt85PDBAufxO5bLeZ1W8StDPeb8+c6b83S3VmkbiL2HNjqCKDF82ozfg2N+jWYwh15iAVKKUTCgPPWz0SZaHJkg6hCvNetEnZAlD7VvVdwzFsvVQXzU+43ypdtNbkzcvH1kimOgmFvRE5hbAFlQSeC+j8ZzS/yffFkI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790180255; c=relaxed/simple; bh=sbnmurq/uAX+vNJcFUT4c5jU9IwDiC579Dx07vz6Q7Y=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=bkAwp0ar6KP7zMdvs5ITZ2IkRN6O23CZPbxHcjleUX41SNg9OkPm566qW4rUkHlCGOyg0W9gLzeEdI08DI8t8/Cd3eMXWb8odUaCBkIWtYOKgTljC7uGGgfUAK/+1wdbhD3wiPUzRK7jGCLybqDUO3uXZnj9lXwfZYruDP/fJas= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=q7DczvZl; arc=none smtp.client-ip=209.85.221.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="q7DczvZl" Received: by mail-wr1-f50.google.com with SMTP id ffacd0b85a97d-48586861639so17051f8f.0 for ; Wed, 23 Sep 2026 09:17:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790180252; x=1790785052; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=6FsqUSBp8jlzbulaQzZnxDz2zVSSSTOE4AXgMopXxYY=; b=q7DczvZleVowyfmR//K2jhBCDx0FX6D86DjOCweqf0hKEE8zwvFpJUksV5TwmG+6AR bclRVLedfwtMqBMN0xX9u2VmZ/IXgXaWTWqZ7zKfMVlzp8G7B66Km1HEEps2H5PsogK+ /V/d56NZRn3QkCUC17WIeiPPBcfSFTAFmX2H5IsRH0opIJ4343UMaicQXN6WeL96vONF 6QHlobj0fijbv3GNGdmyNso+9FtFwD5dTi6+bc5ZwQJb6IGi5AiU6WIN3P8hHlTkkkJM ZCuYYoJVYgGI+GM4a99LJQDnD6OomFVCMqa4P/L+18wasKyjRtv11TP5CP8znIyUtuW9 raAw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790180252; x=1790785052; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=6FsqUSBp8jlzbulaQzZnxDz2zVSSSTOE4AXgMopXxYY=; b=cQOijeUflsnHjkaVhJMiPcmM7uSdNjxQnnl0qJ8Pw2Jy0q2njOSyx7zap0FJEajMa3 glraGX5AViJHPdX4XzphjbFsqObGDqMMNihY2uBqGPr5Kkg2zyJW2C70amM7Bv7dR9Y+ AdBzqZndlvjNTKmmfQVoEqKpl3LKV1gorTV11iRkQsPHWDP0HaHb55V/cpwqxAlLPjhi 4waG4lbkwJ9I0CiWCm7+A1MkLW9B+LDrX9rpoZrZqeUXBV/EP+bkrhBsmi1B6qhygxR/ t+akXocvdf/AObPjrE+fmPnnp7ClzeTZqylIFYcNZ0b/MxiKknqpZ7XHDteTZFcctDT0 ytjQ== X-Gm-Message-State: AFuF++lpSvNZnrrmZs9TnCIiRyWxiTgkkUyRt5S8jX5LBlsScA5Jq/Il bBUgf2qfG24D5b18WWekT1A8uazl3BFhuhoAQYdbHAlAycpgBIExUkj3bcg+J+G9QlahNw== X-Gm-Gg: AYBFou3Lyf9SFuvLTfNsQqF5dKuKzawmuTd6wXkgOpEWVO/aGdLqQi/R7SmbMwCWBTG FGSgPm4aNLoLcI7YcxGE1pfIKl81dnaqUlvuwVVY1ouO54apOawTpJf764/XsnbGxtVNtAXKIHS rJkcgXoLTV6cj5Hb9nAQBMBMlfbz4ax7oI6oueIeglwoysT06ajdjhjwkCBgVYsbAzAusnBo9WD kSnQMf20WtxhQxQfL6uE0ml8R+uI8B+W25IXRSFmMbd72rize9mb1scr4jM6PfzaMFd69ZV1NkI p+kjJFbhUmvPhueuhG56lxUW7vfjkMSzOWoiseZbumLMNYt4pGRjGSDBVnLqvRMcvcIYUp8yfQO 1iO+ST0uB8kXTa52gaFqE6XrQ42ugCuKxCqzzLdKxGdBq1oRCdvVjXk7IJUB2zzu2slOzA8cGhO rNA4TaSe2BY3Vz8ZogNtV1eYZU8ZnAcr0/YC1k3dXCbH8mrPmVDgK7DHOFrZZVeejn1us2234Vi cD6JF56O740Fx1tnxfx+DTSgrhuc1/dmk6bZIAJdQ4HCIH+3ZHUlQ5DONt2YBYqbFFiUe4BY4vR RA== X-Received: by 2002:a05:6000:1788:b0:487:22b1:e511 with SMTP id ffacd0b85a97d-48860f8dca0mr13416589f8f.9.1790180251439; Wed, 23 Sep 2026 09:17:31 -0700 (PDT) Received: from Raghu007.. (sgyl-44-b2-v4wan-174108-cust110.vm6.cable.virginm.net. [80.1.81.111]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-48867b49661sm7602716f8f.0.2026.09.23.09.17.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 23 Sep 2026 09:17:30 -0700 (PDT) From: Palla Raghunath To: linux-kernel@vger.kernel.org Cc: Shuah Khan , Brigham Campbell , linux-kernel-mentees@lists.linux.dev, raghunathpalla.0209@gmail.com, syzbot+422b372cabfbaa528725@syzkaller.appspotmail.com, Song Liu , Yu Kuai , Li Nan , Xiao Ni , NeilBrown , "Trela, Maciej" , linux-raid@vger.kernel.org Subject: [PATCH] md/raid0: don't BUG() on a bio that lands off the end of the array Date: Wed, 23 Sep 2026 17:17:28 +0100 Message-Id: <20260923161729.122240-1-raghunathpalla.0209@gmail.com> X-Mailer: git-send-email 2.34.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" find_zone() looks for the strip zone holding a given sector and BUG()s if it can't find one. That is only a safe assumption while the capacity the array advertises matches what the zones actually cover, and a personality takeover can break exactly that. level_store() lets you switch a live array to a different personality. The new ->run() recalculates mddev->array_sectors, but level_store() never tells the gendisk about it - it is the one place in md that changes the array size without a set_capacity_and_notify(), which do_md_run(), array_size_store(), update_size(), md_reap_sync_thread() and linear_add() all do. So when a takeover makes the array smaller, the block device goes on advertising the old size and I/O sails off the end of the new mapping. syzbot got there with a raid1 that had no metadata. Such a member comes in through md_import_device(dev, -1, -1), which never sets rdev->sectors, and the check in bind_rdev_to_array() that keeps mddev->dev_sectors inside the member is skipped precisely when rdev->sectors is 0: if (!test_bit(Journal, &rdev->flags) && rdev->sectors && (mddev->dev_sectors =3D=3D 0 || rdev->sectors < mddev->dev_sectors)) { md/component_size had set dev_sectors to 2048, so raid1 came up with array_sectors =3D 2048 and the disk got a 2048 sector capacity. Writing "raid0" to md/level then took the array over: create_strip_zones() rounded rdev->sectors (0) down to a chunk multiple, so the single strip zone ended at 0 and raid0_size() returned 0. The capacity stayed at 2048, so the partition scan on the next open of /dev/md0 read sector 0 and fell over: kernel BUG at drivers/md/raid0.c:318! RIP: 0010:find_zone drivers/md/raid0.c:318 [inline] RIP: 0010:raid0_map_submit_bio drivers/md/raid0.c:568 [inline] RIP: 0010:raid0_make_request+0xf17/0x10b0 drivers/md/raid0.c:626 Call Trace: md_handle_request+0xb0a/0xe60 drivers/md/md.c:417 __submit_bio+0x27f/0x340 block/blk-core.c:681 submit_bio_noacct_nocheck+0x4e8/0xa40 block/blk-core.c:792 block_read_full_folio+0x7a6/0x810 fs/buffer.c:2373 read_part_sector+0xb6/0x2b0 block/partitions/core.c:724 adfspart_check_ICS+0xb1/0x960 block/partitions/acorn.c:357 bdev_disk_changed+0x851/0x17a0 block/partitions/core.c:695 blkdev_get_whole+0x372/0x510 block/bdev.c:793 bdev_open+0x324/0xd70 block/bdev.c:1002 blkdev_open+0x461/0x600 block/fops.c:674 __x64_sys_openat+0x138/0x170 fs/open.c:1434 Just refreshing the capacity in level_store() is not enough on its own. If the size is managed externally - md/array_size written while the array was stopped, which slips past array_size_store()'s -E2BIG check - md_set_array_sectors() does nothing, array_sectors keeps the larger value and we BUG() all the same. level_store() cannot turn the takeover away the way do_md_run() does either, because ->takeover() has already run and the old personality has already been freed. md-linear has always just failed a sector outside its mapping instead of asserting, so do the same here: let find_zone() return NULL and have its two callers report the bio and end it with an I/O error. Tested both ways into this state - a takeover that leaves the array zero-length, and one where md/array_size pins array_sectors at 2048. Before, each panics in find_zone(); after, the read just fails: md/raid0:md0: sector 0 out of bounds, array size 0 md/raid0:md0: sector 0 out of bounds, array size 2048 Reported-by: syzbot+422b372cabfbaa528725@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=3D422b372cabfbaa528725 Fixes: 9af204cf720c ("md: Add support for Raid5->Raid0 and Raid10->Raid0 ta= keover") Signed-off-by: Palla Raghunath --- drivers/md/raid0.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 35e103f0c2c3..04c022d74fae 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -301,6 +301,7 @@ static int create_strip_zones(struct mddev *mddev, stru= ct r0conf **private_conf) =20 /* Find the zone which holds a particular offset * Update *sectorp to be an offset in that zone + * Returns NULL if the sector is off the end of the array. */ static struct strip_zone *find_zone(struct r0conf *conf, sector_t *sectorp) @@ -315,7 +316,16 @@ static struct strip_zone *find_zone(struct r0conf *con= f, *sectorp =3D sector - z[i-1].zone_end; return z + i; } - BUG(); + return NULL; +} + +static void raid0_out_of_bounds(struct mddev *mddev, struct bio *bio) +{ + pr_err_ratelimited("md/raid0:%s: sector %llu out of bounds, array size %l= lu\n", + mdname(mddev), + (unsigned long long)bio->bi_iter.bi_sector, + (unsigned long long)mddev->array_sectors); + bio_io_error(bio); } =20 /* @@ -471,6 +481,10 @@ static void raid0_handle_discard(struct mddev *mddev, = struct bio *bio) =20 orig_start =3D start; zone =3D find_zone(conf, &start); + if (!zone) { + raid0_out_of_bounds(mddev, bio); + return; + } =20 if (bio_end_sector(bio) > zone->zone_end) { bio =3D bio_submit_split_bioset(bio, @@ -566,6 +580,11 @@ static void raid0_map_submit_bio(struct mddev *mddev, = struct bio *bio) md_account_bio(mddev, &bio); =20 zone =3D find_zone(mddev->private, §or); + if (!zone) { + raid0_out_of_bounds(mddev, bio); + return; + } + switch (conf->layout) { case RAID0_ORIG_LAYOUT: tmp_dev =3D map_sector(mddev, zone, bio_sector, §or); --=20 2.34.1