From: Yu Kuai <yukuai1@huaweicloud.com>
To: Wang Jinchao <wangjinchao600@gmail.com>, Song Liu <song@kernel.org>
Cc: linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org,
"yukuai (C)" <yukuai3@huawei.com>
Subject: Re: [PATCH v2] md/raid1: Fix stack memory use after return in raid1_reshape
Date: Thu, 12 Jun 2025 15:31:22 +0800 [thread overview]
Message-ID: <5143c5c3-3a77-919f-0d38-8adb0e8923e9@huaweicloud.com> (raw)
In-Reply-To: <20250611090203.271488-1-wangjinchao600@gmail.com>
Hi,
在 2025/06/11 16:55, Wang Jinchao 写道:
> In the raid1_reshape function, newpool is
> allocated on the stack and assigned to conf->r1bio_pool.
> This results in conf->r1bio_pool.wait.head pointing
> to a stack address.
> Accessing this address later can lead to a kernel panic.
>
> Example access path:
>
> raid1_reshape()
> {
> // newpool is on the stack
> mempool_t newpool, oldpool;
> // initialize newpool.wait.head to stack address
> mempool_init(&newpool, ...);
> conf->r1bio_pool = newpool;
> }
>
> raid1_read_request() or raid1_write_request()
> {
> alloc_r1bio()
> {
> mempool_alloc()
> {
> // if pool->alloc fails
> remove_element()
> {
> --pool->curr_nr;
> }
> }
> }
> }
>
> mempool_free()
> {
> if (pool->curr_nr < pool->min_nr) {
> // pool->wait.head is a stack address
> // wake_up() will try to access this invalid address
> // which leads to a kernel panic
> return;
> wake_up(&pool->wait);
> }
> }
>
> Fix:
> The solution is to avoid using a stack-based newpool.
> Instead, directly initialize conf->r1bio_pool.
>
> Signed-off-by: Wang Jinchao <wangjinchao600@gmail.com>
> ---
> v1 -> v2:
> - change subject
> - use mempool_init(&conf->r1bio_pool) instead of reinitializing the list on stack
> ---
> drivers/md/raid1.c | 34 +++++++++++++++++++---------------
> 1 file changed, 19 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
> index 19c5a0ce5a40..f2436262092a 100644
> --- a/drivers/md/raid1.c
> +++ b/drivers/md/raid1.c
> @@ -3366,7 +3366,7 @@ static int raid1_reshape(struct mddev *mddev)
> * At the same time, we "pack" the devices so that all the missing
> * devices have the higher raid_disk numbers.
> */
> - mempool_t newpool, oldpool;
> + mempool_t oldpool;
> struct pool_info *newpoolinfo;
> struct raid1_info *newmirrors;
> struct r1conf *conf = mddev->private;
> @@ -3375,9 +3375,6 @@ static int raid1_reshape(struct mddev *mddev)
> int d, d2;
> int ret;
>
> - memset(&newpool, 0, sizeof(newpool));
> - memset(&oldpool, 0, sizeof(oldpool));
> -
> /* Cannot change chunk_size, layout, or level */
> if (mddev->chunk_sectors != mddev->new_chunk_sectors ||
> mddev->layout != mddev->new_layout ||
> @@ -3408,26 +3405,33 @@ static int raid1_reshape(struct mddev *mddev)
> newpoolinfo->mddev = mddev;
> newpoolinfo->raid_disks = raid_disks * 2;
>
> - ret = mempool_init(&newpool, NR_RAID_BIOS, r1bio_pool_alloc,
> - rbio_pool_free, newpoolinfo);
> - if (ret) {
> - kfree(newpoolinfo);
> - return ret;
> - }
> newmirrors = kzalloc(array3_size(sizeof(struct raid1_info),
> - raid_disks, 2),
> - GFP_KERNEL);
> + raid_disks, 2),
> + GFP_KERNEL);
> if (!newmirrors) {
> kfree(newpoolinfo);
> - mempool_exit(&newpool);
> return -ENOMEM;
> }
>
> + /* stop everything before switching the pool */
> freeze_array(conf, 0);
>
> - /* ok, everything is stopped */
> + /* backup old pool in case restore is needed */
> oldpool = conf->r1bio_pool;
> - conf->r1bio_pool = newpool;
> +
> + ret = mempool_init(&conf->r1bio_pool, NR_RAID_BIOS, r1bio_pool_alloc,
> + rbio_pool_free, newpoolinfo);
> + if (ret) {
> + kfree(newpoolinfo);
> + kfree(newmirrors);
> + mempool_exit(&conf->r1bio_pool);
> + /* restore the old pool */
> + conf->r1bio_pool = oldpool;
> + unfreeze_array(conf);
> + pr_err("md/raid1:%s: cannot allocate r1bio_pool for reshape\n",
> + mdname(mddev));
> + return ret;
> + }
>
> for (d = d2 = 0; d < conf->raid_disks; d++) {
> struct md_rdev *rdev = conf->mirrors[d].rdev;
>
Any specific reason not to use mempool_resize() and krealloc() here?
In the case if new raid_disks is greater than the old one.
Thanks,
Kuai
next prev parent reply other threads:[~2025-06-12 7:31 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-11 8:55 [PATCH v2] md/raid1: Fix stack memory use after return in raid1_reshape Wang Jinchao
2025-06-12 7:31 ` Yu Kuai [this message]
2025-06-12 7:45 ` Wang Jinchao
2025-06-12 9:17 ` Yu Kuai
2025-06-12 9:55 ` Wang Jinchao
2025-06-12 11:23 ` Yu Kuai
2025-06-12 11:46 ` Wang Jinchao
2025-06-12 11:58 ` Yu Kuai
2025-06-12 12:21 ` Wang Jinchao
2025-06-13 9:15 ` Yu Kuai
2025-06-13 11:53 ` Wang Jinchao
2025-06-16 10:11 ` Wang Jinchao
2025-06-16 11:32 ` Yu Kuai
2025-06-18 11:47 ` Wang Jinchao
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5143c5c3-3a77-919f-0d38-8adb0e8923e9@huaweicloud.com \
--to=yukuai1@huaweicloud.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-raid@vger.kernel.org \
--cc=song@kernel.org \
--cc=wangjinchao600@gmail.com \
--cc=yukuai3@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).