From: sashiko-bot@kernel.org
To: "Yu Kuai" <yukuai@kernel.org>
Cc: linux-raid@vger.kernel.org, yukuai@fygo.io
Subject: Re: [PATCH v3 09/21] md/md-llbitmap: finish reshape geometry
Date: Tue, 28 Jul 2026 09:14:14 +0000 [thread overview]
Message-ID: <20260728091415.036311F000E9@smtp.kernel.org> (raw)
In-Reply-To: <ed61e406f8b6b60193c647ab83dd8fb5df0391d0.1785206690.git.yukuai@fygo.io>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
New issues:
- [High] The newly implemented `.reshape_finish` callback is never called by the md core, leaving the staged geometry uncommitted at runtime.
- [High] Concurrent array resize causes Use-After-Free of `llbitmap->pctl`.
Pre-existing issues:
- [High] Teardown symmetry violation in `llbitmap_destroy` leading to UAF on `llbitmap`.
- [High] Permanent crippling of the bitmap daemon expiration logic after any flush operation.
--
--- Patch [9]: [PATCH v3 09/21] md/md-llbitmap: finish reshape geometry ---
commit 83899f955ca5cb817105e296dabf1a5632ece1df
Author: Yu Kuai <yukuai@fygo.io>
md/md-llbitmap: finish reshape geometry
When assembling a stopped reshape, md_run() creates the bitmap before
publishing mddev->pers. This commit refreshes the staged reshape geometry
again from llbitmap_load() after mddev->pers is available, and expands
the in-memory page controls before replaying bitmap state.
Link: https://lore.kernel.org/all/20260726185916.2223460-1-mykola@meshstor.io/
> diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c
> index cdced2126e975..55ab2a8a11e5f 100644
> --- a/drivers/md/md-llbitmap.c
> +++ b/drivers/md/md-llbitmap.c
> @@ -1349,11 +1349,20 @@ static int llbitmap_load(struct mddev *mddev)
> {
> enum llbitmap_action action = BitmapActionReload;
> struct llbitmap *llbitmap = mddev->bitmap;
> + int ret;
>
> if (test_and_clear_bit(BITMAP_STALE, &llbitmap->flags))
> action = BitmapActionStale;
>
> + mutex_lock(&mddev->bitmap_info.mutex);
> + llbitmap_refresh_reshape(llbitmap);
> + ret = llbitmap_expand_pages(llbitmap, llbitmap->chunks);
[Severity: High]
Can this concurrent array resize cause a use-after-free of the page control
array?
If llbitmap_expand_pages() frees the active pctl array while replacing it
with a new one:
drivers/md/md-llbitmap.c:llbitmap_expand_pages() {
...
kfree(llbitmap->pctl);
llbitmap->pctl = pctl;
...
}
Normal read/write I/O paths like llbitmap_start_write() call
llbitmap_raise_barrier(), which locklessly dereferences the array:
drivers/md/md-llbitmap.c:llbitmap_raise_barrier() {
...
struct llbitmap_page_ctl *pctl = llbitmap->pctl[page_idx];
...
}
Does this require synchronization, such as quiesce or RCU, to safely update
the array without causing a use-after-free during concurrent I/O?
> + if (ret) {
> + mutex_unlock(&mddev->bitmap_info.mutex);
> + return ret;
> + }
> llbitmap_state_machine(llbitmap, 0, llbitmap->chunks - 1, action);
> + mutex_unlock(&mddev->bitmap_info.mutex);
> return 0;
> }
>
[ ... ]
> @@ -1680,6 +1689,30 @@ static void llbitmap_dirty_bits(struct mddev *mddev, unsigned long s,
> llbitmap_state_machine(mddev->bitmap, s, e, BitmapActionStartwrite);
> }
>
> +static void llbitmap_reshape_finish(struct mddev *mddev)
> +{
> + struct llbitmap *llbitmap = mddev->bitmap;
> +
> + if (mddev->pers->quiesce)
> + mddev->pers->quiesce(mddev, 1);
> +
> + mutex_lock(&mddev->bitmap_info.mutex);
> + llbitmap_flush(mddev);
[Severity: High]
This is a pre-existing issue, but does calling llbitmap_flush() permanently
cripple the bitmap daemon's expiration logic?
llbitmap_flush() sets the LLPageFlush flag on all page control structures to
force immediate flushing:
drivers/md/md-llbitmap.c:llbitmap_flush() {
...
for (i = 0; i < llbitmap->nr_pages; i++)
set_bit(LLPageFlush, &llbitmap->pctl[i]->flags);
...
}
The daemon skips the expiration check if this flag is set:
drivers/md/md-llbitmap.c:md_llbitmap_daemon_fn() {
...
if (!test_bit(LLPageFlush, &pctl->flags) &&
time_before(jiffies, pctl->expire)) {
restart = true;
continue;
...
}
Since there doesn't seem to be a corresponding mechanism to ever clear the
LLPageFlush flag, won't all subsequent I/O bypass write batching and flush
immediately?
> +
> + llbitmap->chunksize = llbitmap->reshape_chunksize;
> + llbitmap->chunkshift = ffz(~llbitmap->chunksize);
> + llbitmap->chunks = llbitmap->reshape_chunks;
> + llbitmap->sync_size = llbitmap->reshape_sync_size;
> + llbitmap_refresh_reshape(llbitmap);
> + mddev->bitmap_info.chunksize = llbitmap->chunksize;
> + llbitmap_update_sb(llbitmap);
> + __llbitmap_flush(mddev);
> + mutex_unlock(&mddev->bitmap_info.mutex);
> +
> + if (mddev->pers->quiesce)
> + mddev->pers->quiesce(mddev, 0);
> +}
> +
[ ... ]
> @@ -1977,6 +2010,7 @@ static struct bitmap_operations llbitmap_ops = {
> .get_stats = llbitmap_get_stats,
> .dirty_bits = llbitmap_dirty_bits,
> .prepare_range = llbitmap_prepare_range,
> + .reshape_finish = llbitmap_reshape_finish,
[Severity: High]
Is the newly added .reshape_finish callback ever invoked by the md core?
Without a caller in the md core, it appears the staged reshape geometry
remains uncommitted at runtime, which would leave the active geometry stale.
Can this result in incorrect bitmap behavior or data corruption during or
after a reshape?
> .write_all = llbitmap_write_all,
>
> .groups = md_llbitmap_groups,
As a side note, I noticed another pre-existing issue in the teardown path:
[Severity: High]
This is a pre-existing issue, but does llbitmap_destroy() have a teardown
symmetry violation that could lead to a use-after-free on the llbitmap
structure?
When stopping an array, llbitmap_destroy() deletes the timer and flushes the
workqueue without setting a termination flag:
drivers/md/md-llbitmap.c:llbitmap_destroy() {
...
timer_delete_sync(&llbitmap->pending_timer);
flush_workqueue(md_llbitmap_io_wq);
flush_workqueue(md_llbitmap_unplug_wq);
mddev->bitmap = NULL;
llbitmap_free_pages(llbitmap);
kfree(llbitmap);
}
If the daemon work item executes on the workqueue, it can re-arm the timer if
there are unexpired dirty pages:
drivers/md/md-llbitmap.c:md_llbitmap_daemon_fn() {
...
if (restart)
mod_timer(&llbitmap->pending_timer,
jiffies + llbitmap->mddev->bitmap_info.daemon_sleep * HZ);
...
}
Because md_llbitmap_daemon_fn() doesn't check for a teardown flag, couldn't
the timer be re-armed, and then fire later on the freed llbitmap memory after
llbitmap_destroy() completes?
--
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1785206690.git.yukuai@fygo.io?part=9
next prev parent reply other threads:[~2026-07-28 9:14 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-28 8:49 [PATCH v3 00/21] md/md-llbitmap: support reshape for RAID10 and RAID5 Yu Kuai
2026-07-28 8:49 ` [PATCH v3 01/21] md/raid5: round bitmap stripes with sector division Yu Kuai
2026-07-28 9:03 ` sashiko-bot
2026-07-28 8:49 ` [PATCH v3 02/21] md: add exact bitmap mapping and reshape hooks Yu Kuai
2026-07-28 8:49 ` [PATCH v3 03/21] md: skip bitmap accounting for empty write ranges Yu Kuai
2026-07-28 8:49 ` [PATCH v3 04/21] md: add helper to split bios at reshape offset Yu Kuai
2026-07-28 9:03 ` sashiko-bot
2026-07-28 8:49 ` [PATCH v3 05/21] md/md-llbitmap: track bitmap sync_size explicitly Yu Kuai
2026-07-28 9:16 ` sashiko-bot
2026-07-28 8:49 ` [PATCH v3 06/21] md/md-llbitmap: allocate page controls independently Yu Kuai
2026-07-28 9:06 ` sashiko-bot
2026-07-28 8:49 ` [PATCH v3 07/21] md/md-llbitmap: grow the page cache in place for reshape Yu Kuai
2026-07-28 9:09 ` sashiko-bot
2026-07-28 8:49 ` [PATCH v3 08/21] md/md-llbitmap: track target reshape geometry fields Yu Kuai
2026-07-28 9:12 ` sashiko-bot
2026-07-28 8:49 ` [PATCH v3 09/21] md/md-llbitmap: finish reshape geometry Yu Kuai
2026-07-28 9:14 ` sashiko-bot [this message]
2026-07-28 8:49 ` [PATCH v3 10/21] md/md-llbitmap: refuse reshape while llbitmap still needs sync Yu Kuai
2026-07-28 9:12 ` sashiko-bot
2026-07-28 8:49 ` [PATCH v3 11/21] md/md-llbitmap: add reshape range mapping helpers Yu Kuai
2026-07-28 9:11 ` sashiko-bot
2026-07-28 8:49 ` [PATCH v3 12/21] md/md-llbitmap: don't skip reshape ranges from bitmap state Yu Kuai
2026-07-28 8:49 ` [PATCH v3 13/21] md/md-llbitmap: remap checkpointed bits as reshape progresses Yu Kuai
2026-07-28 9:06 ` sashiko-bot
2026-07-28 8:49 ` [PATCH v3 14/21] md/md-llbitmap: clamp state-machine walks to tracked bits Yu Kuai
2026-07-28 9:13 ` sashiko-bot
2026-07-28 8:49 ` [PATCH v3 15/21] md/raid10: reject llbitmap reshape when md chunk shrinks Yu Kuai
2026-07-28 9:15 ` sashiko-bot
2026-07-28 8:49 ` [PATCH v3 16/21] md/raid10: wire llbitmap reshape lifecycle Yu Kuai
2026-07-28 9:22 ` sashiko-bot
2026-07-28 8:49 ` [PATCH v3 17/21] md/raid10: split reshape bios before bitmap accounting Yu Kuai
2026-07-28 9:15 ` sashiko-bot
2026-07-28 8:49 ` [PATCH v3 18/21] md/raid5: add exact old and new llbitmap mapping helpers Yu Kuai
2026-07-28 9:25 ` sashiko-bot
2026-07-28 8:49 ` [PATCH v3 19/21] md/raid5: reject llbitmap reshape when md chunk shrinks Yu Kuai
2026-07-28 9:22 ` sashiko-bot
2026-07-28 8:49 ` [PATCH v3 20/21] md/raid5: wire llbitmap reshape lifecycle Yu Kuai
2026-07-28 9:21 ` sashiko-bot
2026-07-28 8:49 ` [PATCH v3 21/21] md/raid5: split reshape bios before bitmap accounting Yu Kuai
2026-07-28 9:26 ` sashiko-bot
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=20260728091415.036311F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=linux-raid@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=yukuai@fygo.io \
--cc=yukuai@kernel.org \
/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