Re: [PATCH v5 09/29] md/md-llbitmap: stop daemon timer rearm on destroy

[email protected] Sun, 02 Aug 2026 20:19:03 +0000
Newsgroups org.kernel.vger.linux-raid
Message-ID <[email protected]>
Thank you for your contribution! Sashiko AI review found 1 potential issue(=
s) to consider:

Pre-existing issues:
- [High] Time-of-check to time-of-use (TOCTOU) race in the teardown path al=
lows the timer to be re-armed after deletion, causing a use-after-free.
--

--- Patch [9]: [PATCH v5 09/29] md/md-llbitmap: stop daemon timer rearm on =
destroy ---
commit ea383c856bd9022c7e57c7a025fcf8fb539acf1e
Author: Yu Kuai <[email protected]>

md/md-llbitmap: stop daemon timer rearm on destroy

This commit attempts to fix a race where the daemon timer is re-armed
during array teardown. It adds a BITMAP_SHUTDOWN flag, sets it before
deleting the timer and canceling the daemon work, and checks the flag
before queuing or rearming the work.

> diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c
> --- a/drivers/md/md-llbitmap.c
> +++ b/drivers/md/md-llbitmap.c

[ ... ]

> @@ -1096,7 +1103,7 @@ static void md_llbitmap_daemon_fn(struct work_struc=
t *work)
>  		goto retry;
> =20
>  	/* If some page is dirty but not expired, setup timer again */
> -	if (restart)
> +	if (restart && !test_bit(BITMAP_SHUTDOWN, &llbitmap->flags))
>  		mod_timer(&llbitmap->pending_timer,
>  			  jiffies + llbitmap->mddev->bitmap_info.daemon_sleep * HZ);
>  }

[ ... ]

> @@ -1179,7 +1186,9 @@ static void llbitmap_destroy(struct mddev *mddev)
> =20
>  	mutex_lock(&mddev->bitmap_info.mutex);
> =20
> +	set_bit(BITMAP_SHUTDOWN, &llbitmap->flags);
>  	timer_delete_sync(&llbitmap->pending_timer);
> +	cancel_work_sync(&llbitmap->daemon_work);
>  	flush_workqueue(md_llbitmap_io_wq);
>  	flush_workqueue(md_llbitmap_unplug_wq);

[Severity: High]
This isn't a bug introduced by this patch, but does this teardown sequence
still leave a race condition that can result in a use-after-free?

Since the BITMAP_SHUTDOWN check and mod_timer() in md_llbitmap_daemon_fn()
are not atomic, a worker can evaluate BITMAP_SHUTDOWN as false but get
preempted before arming the timer.

Concurrently, llbitmap_destroy() sets BITMAP_SHUTDOWN, calls
timer_delete_sync() (which returns immediately if the timer isn't pending),
and blocks in cancel_work_sync().

When the preempted worker resumes, it executes mod_timer(), re-arming the
timer. Once the worker finishes, cancel_work_sync() unblocks and
llbitmap_destroy() frees llbitmap, leaving the timer armed and able to
access freed memory when it fires.

Would replacing timer_delete_sync() with timer_shutdown_sync() safely
prevent any subsequent mod_timer() calls from succeeding?

--=20
Sashiko AI review =C2=B7 https://sashiko.dev/#/patchset/20260802195038.1642=
[email protected]?part=3D9