From: ghuicao@163.com
To: Song Liu <song@kernel.org>
Cc: Yu Kuai <yukuai@fygo.io>, Li Nan <magiclinan@didiglobal.com>,
Xiao Ni <xiao@kernel.org>,
linux-raid@vger.kernel.org, linux-kernel@vger.kernel.org,
stable@vger.kernel.org, Cao Guanghui <caoguanghui@kylinos.cn>
Subject: [PATCH v2 2/3] md/raid5: fix leak and use-after-free in resize_stripes error path
Date: Thu, 27 Aug 2026 14:05:53 +0800 [thread overview]
Message-ID: <20260827060554.77849-2-ghuicao@163.com> (raw)
In-Reply-To: <20260827060554.77849-1-ghuicao@163.com>
From: Cao Guanghui <caoguanghui@kylinos.cn>
resize_stripes() has two issues in how conf->disks is replaced:
1. Memory leak: conf->disks is replaced with ndisks in Step 3, but
pool_size is only updated at the end with "if (!err)". If Step 4
(allocating pages for new stripe slots) fails, pool_size retains the
old value. On teardown, free_conf() iterates only pool_size entries,
leaking (newsize - pool_size) extra_page allocations.
2. Use-after-free: conf->disks is freed and replaced without holding
mddev->lock, while raid5_status() (called from /proc/mdstat via
md_seq_show) reads conf->disks[i].rdev under mddev->lock. The
freeing and replacement happen under reconfig_mutex and
cache_size_mutex, which do not exclude mddev->lock holders.
Fix both by deferring the conf->disks replacement until after Step 4
succeeds, and performing the pointer swap under mddev->lock so that
concurrent readers in raid5_status() see either the old or new array,
never a freed one. If Step 4 fails, ndisks is freed instead.
This also preserves the original retry behavior: pool_size is only
updated on full success, so check_reshape() correctly calls
resize_stripes() again on retry.
Fixes: ad01c9e3752f ("[PATCH] md: Allow stripes to be expanded in preparation for expanding an array")
Cc: stable@vger.kernel.org
Signed-off-by: Cao Guanghui <caoguanghui@kylinos.cn>
---
Changes in v2:
- Defer conf->disks replacement to after Step 4 instead of setting
pool_size early, which would break reshape retry logic (Sashiko)
- Add spinlock protection around the pointer swap to fix a concurrent
use-after-free in raid5_status() (Sashiko)
drivers/md/raid5.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -2639,9 +2639,7 @@ static int resize_stripes(struct r5conf *conf, int newsize)
if (ndisks[i].extra_page)
put_page(ndisks[i].extra_page);
kfree(ndisks);
- } else {
- kfree(conf->disks);
- conf->disks = ndisks;
+ ndisks = NULL;
}
} else
err = -ENOMEM;
@@ -2685,8 +2683,20 @@ static int resize_stripes(struct r5conf *conf, int newsize)
}
/* critical section pass, GFP_NOIO no longer needed */
- if (!err)
+ if (!err && ndisks) {
+ struct disk_info *old_disks = conf->disks;
+
+ spin_lock_irq(&conf->mddev->lock);
+ conf->disks = ndisks;
+ spin_unlock_irq(&conf->mddev->lock);
+ kfree(old_disks);
conf->pool_size = newsize;
+ } else if (ndisks) {
+ for (i = conf->pool_size; i < newsize; i++)
+ if (ndisks[i].extra_page)
+ put_page(ndisks[i].extra_page);
+ kfree(ndisks);
+ }
mutex_unlock(&conf->cache_size_mutex);
return err;
--
2.34.1
next prev parent reply other threads:[~2026-08-27 6:06 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-27 2:38 [PATCH] md/raid5: set pool_size before extra_page allocation to fix leak on error path ghuicao
2026-08-27 2:53 ` sashiko-bot
2026-08-27 6:05 ` [PATCH v2 1/3] " ghuicao
2026-08-27 6:05 ` ghuicao [this message]
2026-08-27 6:27 ` [PATCH v2 2/3] md/raid5: fix leak and use-after-free in resize_stripes " sashiko-bot
2026-08-27 6:05 ` [PATCH v2 3/3] md/raid5: fix NULL pointer dereference in raid5_free_percpu ghuicao
2026-08-27 6:18 ` sashiko-bot
2026-08-27 6:27 ` [PATCH v2 1/3] md/raid5: set pool_size before extra_page allocation to fix leak on error path sashiko-bot
2026-08-27 6:32 ` [PATCH v3 " ghuicao
2026-08-27 6:32 ` [PATCH v3 2/3] md/raid5: fix leak and use-after-free in resize_stripes " ghuicao
2026-08-27 7:02 ` sashiko-bot
2026-08-27 6:32 ` [PATCH v3 3/3] md/raid5: fix NULL pointer dereference in raid5_free_percpu ghuicao
2026-08-27 7:17 ` sashiko-bot
2026-08-27 8:03 ` [PATCH v4 1/2] md/raid5: track disks array size to fix extra_page leak on error paths ghuicao
2026-08-27 8:03 ` [PATCH v4 2/2] md/raid5: fix NULL pointer dereference in raid5_free_percpu ghuicao
2026-08-27 8:19 ` [PATCH v4 1/2] md/raid5: track disks array size to fix extra_page leak on error paths sashiko-bot
2026-09-05 2:34 ` yu kuai
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=20260827060554.77849-2-ghuicao@163.com \
--to=ghuicao@163.com \
--cc=caoguanghui@kylinos.cn \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-raid@vger.kernel.org \
--cc=magiclinan@didiglobal.com \
--cc=song@kernel.org \
--cc=stable@vger.kernel.org \
--cc=xiao@kernel.org \
--cc=yukuai@fygo.io \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.