* [PATCH 1/2] md/raid5: fix pool_size leak in resize_stripes error path
@ 2026-08-27 3:16 ghuicao
2026-08-27 3:16 ` [PATCH 2/2] md/raid5: fix NULL pointer dereference in raid5_free_percpu ghuicao
2026-08-27 3:32 ` [PATCH 1/2] md/raid5: fix pool_size leak in resize_stripes error path sashiko-bot
0 siblings, 2 replies; 3+ messages in thread
From: ghuicao @ 2026-08-27 3:16 UTC (permalink / raw)
To: Song Liu
Cc: Yu Kuai, Li Nan, Xiao Ni, linux-raid, linux-kernel, stable,
Cao Guanghui
From: Cao Guanghui <caoguanghui@kylinos.cn>
In resize_stripes(), conf->disks is replaced with a new array (ndisks)
in Step 3, but pool_size is only updated at the end with
"if (!err) conf->pool_size = newsize". If Step 4 (allocating pages for
new stripes) fails, err is set but pool_size is not updated, even though
conf->disks already has newsize entries.
When the array is later torn down, free_conf() iterates only pool_size
(= old value) entries, leaking (newsize - pool_size) extra_page
allocations.
Set pool_size immediately after replacing conf->disks, so it always
matches the actual array size regardless of subsequent failures.
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>
---
drivers/md/raid5.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -2641,6 +2641,7 @@ static int resize_stripes(struct r5conf *conf, int newsize)
} else {
kfree(conf->disks);
conf->disks = ndisks;
+ conf->pool_size = newsize;
}
} else
err = -ENOMEM;
@@ -2687,5 +2688,3 @@ static int resize_stripes(struct r5conf *conf, int newsize)
/* critical section pass, GFP_NOIO no longer needed */
- if (!err)
- conf->pool_size = newsize;
mutex_unlock(&conf->cache_size_mutex);
--
2.34.1
^ permalink raw reply [flat|nested] 3+ messages in thread* [PATCH 2/2] md/raid5: fix NULL pointer dereference in raid5_free_percpu
2026-08-27 3:16 [PATCH 1/2] md/raid5: fix pool_size leak in resize_stripes error path ghuicao
@ 2026-08-27 3:16 ` ghuicao
2026-08-27 3:32 ` [PATCH 1/2] md/raid5: fix pool_size leak in resize_stripes error path sashiko-bot
1 sibling, 0 replies; 3+ messages in thread
From: ghuicao @ 2026-08-27 3:16 UTC (permalink / raw)
To: Song Liu
Cc: Yu Kuai, Li Nan, Xiao Ni, linux-raid, linux-kernel, stable,
Cao Guanghui
From: Cao Guanghui <caoguanghui@kylinos.cn>
If cpuhp_state_add_instance() fails in raid5_alloc_percpu() (e.g., the
startup callback raid456_cpu_up_prepare fails due to an allocation
failure), conf->node is never added to the cpuhp instance list and
its pprev remains NULL (from kzalloc initialization).
When setup_conf() then jumps to abort, free_conf() calls
raid5_free_percpu(), which checks conf->percpu (non-NULL, since it was
allocated before the cpuhp failure) and proceeds to call
cpuhp_state_remove_instance(). This calls hlist_del() on the unhashed
node, which dereferences node->pprev (NULL), causing a kernel panic.
Guard the removal with hlist_unhashed() so that the cpuhp instance is
only removed if it was actually added.
Fixes: 29c6d1bbd7a2 ("md/raid5: Convert to hotplug state machine")
Cc: stable@vger.kernel.org
Signed-off-by: Cao Guanghui <caoguanghui@kylinos.cn>
---
drivers/md/raid5.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -7539,7 +7539,8 @@ static void raid5_free_percpu(struct r5conf *conf)
{
if (!conf->percpu)
return;
- cpuhp_state_remove_instance(CPUHP_MD_RAID5_PREPARE, &conf->node);
+ if (!hlist_unhashed(&conf->node))
+ cpuhp_state_remove_instance(CPUHP_MD_RAID5_PREPARE, &conf->node);
free_percpu(conf->percpu);
}
--
2.34.1
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH 1/2] md/raid5: fix pool_size leak in resize_stripes error path
2026-08-27 3:16 [PATCH 1/2] md/raid5: fix pool_size leak in resize_stripes error path ghuicao
2026-08-27 3:16 ` [PATCH 2/2] md/raid5: fix NULL pointer dereference in raid5_free_percpu ghuicao
@ 2026-08-27 3:32 ` sashiko-bot
1 sibling, 0 replies; 3+ messages in thread
From: sashiko-bot @ 2026-08-27 3:32 UTC (permalink / raw)
To: ghuicao; +Cc: yukuai, linux-raid
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
New issues:
- [High] Premature update of `pool_size` causes subsequent reshape retries to bypass stripe cache resizing, leading to a NULL pointer dereference.
Pre-existing issues:
- [High] Lockless access to `conf->disks` in `raid5_status()` can lead to a Use-After-Free if it races with `resize_stripes()` freeing the array.
--
commit 021dd13adb2ffa7a0e256f63ee764cd6ee6f46ab
Author: Cao Guanghui <caoguanghui@kylinos.cn>
md/raid5: fix pool_size leak in resize_stripes error path
This commit updates conf->pool_size immediately after replacing conf->disks
in resize_stripes(). It intends to ensure pool_size matches the allocated
array size so free_conf() frees the correct number of extra page allocations
on teardown.
> diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
> index b91545ce090de..fa64cf059b8ea 100644
> --- a/drivers/md/raid5.c
> +++ b/drivers/md/raid5.c
> @@ -2642,6 +2642,7 @@ static int resize_stripes(struct r5conf *conf, int newsize)
> } else {
> kfree(conf->disks);
[Severity: High]
This is a pre-existing issue, but does freeing the old disks array here
without synchronization (e.g., an RCU grace period) allow a use-after-free?
Concurrent readers like raid5_status() access the freed disks array locklessly
since md_seq_show() only holds mddev->lock (a spinlock), while this code
executes under mddev->reconfig_mutex and conf->cache_size_mutex.
For example, in raid5_status():
drivers/md/raid5.c:raid5_status() {
...
struct md_rdev *rdev = READ_ONCE(conf->disks[i].rdev);
...
}
If an unprivileged user reads /proc/mdstat exactly when root initiates a
reshape, it appears the kernel will dereference the memory freed here.
> conf->disks = ndisks;
> + conf->pool_size = newsize;
[Severity: High]
Does moving the pool_size update here cause a NULL pointer dereference on
reshape retries?
If the alloc_page() calls in Step 4 of resize_stripes() fail due to memory
pressure, the function sets err = -ENOMEM and returns, but conf->pool_size
has already been updated to newsize. The stripes are then released into the
cache with missing (NULL) pages.
If a user retries the array reshape operation after the -ENOMEM failure,
check_reshape() will evaluate this condition:
drivers/md/raid5.c:check_reshape() {
...
if (conf->previous_raid_disks + mddev->delta_disks <= conf->pool_size)
return 0; /* never bother to shrink */
...
}
This evaluates to true because pool_size was already updated. The retry
bypasses resize_stripes() and proceeds with the reshape. Later, when
operations like ops_run_io() access the unallocated pages for the new
devices, it results in a NULL pointer dereference.
> }
> } else
> err = -ENOMEM;
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260827031646.49080-1-ghuicao@163.com?part=1
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-08-27 3:32 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-27 3:16 [PATCH 1/2] md/raid5: fix pool_size leak in resize_stripes error path ghuicao
2026-08-27 3:16 ` [PATCH 2/2] md/raid5: fix NULL pointer dereference in raid5_free_percpu ghuicao
2026-08-27 3:32 ` [PATCH 1/2] md/raid5: fix pool_size leak in resize_stripes error path sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox