CVE-2024-43855
Publication date:
17/08/2024
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
md: fix deadlock between mddev_suspend and flush bio<br />
<br />
Deadlock occurs when mddev is being suspended while some flush bio is in<br />
progress. It is a complex issue.<br />
<br />
T1. the first flush is at the ending stage, it clears &#39;mddev->flush_bio&#39;<br />
and tries to submit data, but is blocked because mddev is suspended<br />
by T4.<br />
T2. the second flush sets &#39;mddev->flush_bio&#39;, and attempts to queue<br />
md_submit_flush_data(), which is already running (T1) and won&#39;t<br />
execute again if on the same CPU as T1.<br />
T3. the third flush inc active_io and tries to flush, but is blocked because<br />
&#39;mddev->flush_bio&#39; is not NULL (set by T2).<br />
T4. mddev_suspend() is called and waits for active_io dec to 0 which is inc<br />
by T3.<br />
<br />
T1 T2 T3 T4<br />
(flush 1) (flush 2) (third 3) (suspend)<br />
md_submit_flush_data<br />
mddev->flush_bio = NULL;<br />
.<br />
. md_flush_request<br />
. mddev->flush_bio = bio<br />
. queue submit_flushes<br />
. .<br />
. . md_handle_request<br />
. . active_io + 1<br />
. . md_flush_request<br />
. . wait !mddev->flush_bio<br />
. .<br />
. . mddev_suspend<br />
. . wait !active_io<br />
. .<br />
. submit_flushes<br />
. queue_work md_submit_flush_data<br />
. //md_submit_flush_data is already running (T1)<br />
.<br />
md_handle_request<br />
wait resume<br />
<br />
The root issue is non-atomic inc/dec of active_io during flush process.<br />
active_io is dec before md_submit_flush_data is queued, and inc soon<br />
after md_submit_flush_data() run.<br />
md_flush_request<br />
active_io + 1<br />
submit_flushes<br />
active_io - 1<br />
md_submit_flush_data<br />
md_handle_request<br />
active_io + 1<br />
make_request<br />
active_io - 1<br />
<br />
If active_io is dec after md_handle_request() instead of within<br />
submit_flushes(), make_request() can be called directly intead of<br />
md_handle_request() in md_submit_flush_data(), and active_io will<br />
only inc and dec once in the whole flush process. Deadlock will be<br />
fixed.<br />
<br />
Additionally, the only difference between fixing the issue and before is<br />
that there is no return error handling of make_request(). But after<br />
previous patch cleaned md_write_start(), make_requst() only return error<br />
in raid5_make_request() by dm-raid, see commit 41425f96d7aa ("dm-raid456,<br />
md/raid456: fix a deadlock for dm-raid456 while io concurrent with<br />
reshape)". Since dm always splits data and flush operation into two<br />
separate io, io size of flush submitted by dm always is 0, make_request()<br />
will not be called in md_submit_flush_data(). To prevent future<br />
modifications from introducing issues, add WARN_ON to ensure<br />
make_request() no error is returned in this context.
Severity CVSS v4.0: Pending analysis
Last modification:
03/11/2025