Re: [PATCH v5 16/29] md/md-llbitmap: track target reshape geometry fields
[email protected] Sun, 02 Aug 2026 20:25:05 +0000
| Newsgroups | org.kernel.vger.linux-raid |
|---|---|
| Message-ID | <[email protected]> |
Thank you for your contribution! Sashiko AI review found 2 potential issue(= s) to consider: New issues: - [High] Out-of-bounds array access and memory corruption during reshaping = due to stale chunkshift. Pre-existing issues: - [High] Use-After-Free (UAF) due to a TOCTOU race between teardown and tim= er re-arming in daemon work. -- --- Patch [16]: [PATCH v5 16/29] md/md-llbitmap: track target reshape geome= try fields --- commit dabf6384b9392c331f7703e778887a4f5f7bb15c Author: Yu Kuai <[email protected]> md/md-llbitmap: track target reshape geometry fields =20 Track llbitmap bookkeeping for the target reshape geometry while keeping a single live bitmap instance. =20 Add the reshape geometry fields, refresh helper, and update the load and resize paths to keep the target geometry in sync. > diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c > index ddeea20989873..71a4903901425 100644 > --- a/drivers/md/md-llbitmap.c > +++ b/drivers/md/md-llbitmap.c [ ... ] > @@ -1302,6 +1340,9 @@ static int llbitmap_resize(struct mddev *mddev, sec= tor_t blocks, int chunksize) > goto out; > =20 > if (reshape) { > + llbitmap->reshape_sync_size =3D blocks; > + llbitmap->reshape_chunksize =3D bitmap_chunksize; > + llbitmap->reshape_chunks =3D chunks; > llbitmap->chunks =3D max(old_chunks, chunks); [Severity: High] Does this code need to track or update a chunkshift for the reshape path? During a reshape that increases the array size, bitmap_chunksize might incr= ease. While llbitmap->chunks is clamped here, llbitmap->chunkshift is not updated. Later, if llbitmap_start_write() processes an I/O to the newly extended reg= ion, it uses the stale chunkshift to compute the start chunk: drivers/md/md-llbitmap.c:llbitmap_start_write() { ... unsigned long start =3D offset >> llbitmap->chunkshift; ... } Because chunkshift represents the old, smaller chunk size, start can grossly exceed llbitmap->chunks. Since llbitmap_start_write() lacks bounds checking against llbitmap->chunks, it calculates an out-of-bounds page_start index and calls llbitmap_raise_barrier(), which will directly dereference the llbitmap->pctl array out of bounds. Can this lead to memory corruption? > } else { > if (blocks < old_blocks && chunks < old_chunks) [ ... ] [Severity: High] This is a pre-existing issue, but could the teardown sequence in llbitmap_destroy() race with md_llbitmap_daemon_fn() and cause a use-after-free? In llbitmap_destroy(), the teardown sets the shutdown flag, deletes the timer, and then cancels the daemon work: drivers/md/md-llbitmap.c:llbitmap_destroy() { ... set_bit(BITMAP_SHUTDOWN, &llbitmap->flags); timer_delete_sync(&llbitmap->pending_timer); cancel_work_sync(&llbitmap->daemon_work); ... } However, in md_llbitmap_daemon_fn(), the shutdown check and timer re-arming are not atomic: drivers/md/md-llbitmap.c:md_llbitmap_daemon_fn() { ... if (restart && !test_bit(BITMAP_SHUTDOWN, &llbitmap->flags)) mod_timer(&llbitmap->pending_timer, ...); ... } If the work thread evaluates the check to true and is preempted, llbitmap_destroy() could run, set the shutdown flag, and execute timer_delete_sync() which returns immediately as the timer isn't pending. llbitmap_destroy() then blocks in cancel_work_sync(). When the work thread resumes, it calls mod_timer() to re-arm the timer and exits. cancel_work_sync() then unblocks and llbitmap_destroy() frees the llbitmap object. When the re-armed timer fires, it will access the freed memory. --=20 Sashiko AI review =C2=B7 https://sashiko.dev/#/patchset/20260802195038.1642= [email protected]?part=3D16