The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH] dm-crypt: unlock allocation mutex before retry
@ 2026-08-09  5:18 Runyu Xiao
  2026-08-09 13:20 ` Bart Van Assche
  2026-08-10  9:46 ` Mikulas Patocka
  0 siblings, 2 replies; 3+ messages in thread
From: Runyu Xiao @ 2026-08-09  5:18 UTC (permalink / raw)
  To: agk, snitzer, mpatocka
  Cc: dm-devel, linux-kernel, stable, runyu.xiao, jianhao.xu

If the initial GFP_NOWAIT page allocation fails, crypt_alloc_buffer()
sets __GFP_DIRECT_RECLAIM and retries while holding bio_alloc_lock. If a
later page allocation fails, the retry edge bypasses the common unlock and
reacquires the same mutex. This can deadlock the dm-crypt I/O path and
leave I/O for the affected mapping stalled.

Release the mutex before retrying, but only when this attempt took the
direct-reclaim path; the first attempt did not acquire it.

This issue was identified by a static-analysis checker and manually
confirmed by following the retry control flow in v6.1.66 and current
mainline. A source-level control-flow check verified the vulnerable
ordering and the unlock-before-retry ordering after this change. A small
POSIX-thread model checked only the mutex re-acquisition condition; it does
not exercise dm-crypt.

Fixes: 7145c241a1bf ("dm crypt: avoid deadlock in mempools")
Cc: stable@vger.kernel.org
Signed-off-by: Runyu Xiao <runyu.xiao@seu.edu.cn>
---
 drivers/md/dm-crypt.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 608b617fb817..aabb9a5f85a7 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -1674,6 +1674,8 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned int size)
 		if (!pages) {
 			crypt_free_buffer_pages(cc, clone);
 			bio_put(clone);
+			if (unlikely(gfp_mask & __GFP_DIRECT_RECLAIM))
+				mutex_unlock(&cc->bio_alloc_lock);
 			gfp_mask |= __GFP_DIRECT_RECLAIM;
 			order = 0;
 			goto retry;
-- 
2.34.1

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] dm-crypt: unlock allocation mutex before retry
  2026-08-09  5:18 [PATCH] dm-crypt: unlock allocation mutex before retry Runyu Xiao
@ 2026-08-09 13:20 ` Bart Van Assche
  2026-08-10  9:46 ` Mikulas Patocka
  1 sibling, 0 replies; 3+ messages in thread
From: Bart Van Assche @ 2026-08-09 13:20 UTC (permalink / raw)
  To: Runyu Xiao, agk, snitzer, mpatocka
  Cc: dm-devel, linux-kernel, stable, jianhao.xu

On 8/8/26 10:18 PM, Runyu Xiao wrote:
> diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
> index 608b617fb817..aabb9a5f85a7 100644
> --- a/drivers/md/dm-crypt.c
> +++ b/drivers/md/dm-crypt.c
> @@ -1674,6 +1674,8 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned int size)
>   		if (!pages) {
>   			crypt_free_buffer_pages(cc, clone);
>   			bio_put(clone);
> +			if (unlikely(gfp_mask & __GFP_DIRECT_RECLAIM))
> +				mutex_unlock(&cc->bio_alloc_lock);
>   			gfp_mask |= __GFP_DIRECT_RECLAIM;
>   			order = 0;
>   			goto retry;

Please refactor crypt_alloc_buffer() such that context analysis can be
enabled instead of making this function more complex. One way to do this
is by moving the crypt_alloc_buffer() code that occurs between the
mutex_lock() and mutex_unlock() calls into a helper function.

See also https://docs.kernel.org/dev-tools/context-analysis.html.

Thanks,

Bart.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] dm-crypt: unlock allocation mutex before retry
  2026-08-09  5:18 [PATCH] dm-crypt: unlock allocation mutex before retry Runyu Xiao
  2026-08-09 13:20 ` Bart Van Assche
@ 2026-08-10  9:46 ` Mikulas Patocka
  1 sibling, 0 replies; 3+ messages in thread
From: Mikulas Patocka @ 2026-08-10  9:46 UTC (permalink / raw)
  To: Runyu Xiao; +Cc: agk, snitzer, dm-devel, linux-kernel, stable, jianhao.xu



On Sun, 9 Aug 2026, Runyu Xiao wrote:

> If the initial GFP_NOWAIT page allocation fails, crypt_alloc_buffer()
> sets __GFP_DIRECT_RECLAIM and retries while holding bio_alloc_lock. If a
> later page allocation fails, the retry edge bypasses the common unlock and
> reacquires the same mutex. This can deadlock the dm-crypt I/O path and
> leave I/O for the affected mapping stalled.

Hi

When __GFP_DIRECT_RECLAIM is set, mempool_alloc can't return NULL. So, the 
bug can't happen.

Mikulas

> Release the mutex before retrying, but only when this attempt took the
> direct-reclaim path; the first attempt did not acquire it.
> 
> This issue was identified by a static-analysis checker and manually
> confirmed by following the retry control flow in v6.1.66 and current
> mainline. A source-level control-flow check verified the vulnerable
> ordering and the unlock-before-retry ordering after this change. A small
> POSIX-thread model checked only the mutex re-acquisition condition; it does
> not exercise dm-crypt.
> 
> Fixes: 7145c241a1bf ("dm crypt: avoid deadlock in mempools")
> Cc: stable@vger.kernel.org
> Signed-off-by: Runyu Xiao <runyu.xiao@seu.edu.cn>
> ---
>  drivers/md/dm-crypt.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
> index 608b617fb817..aabb9a5f85a7 100644
> --- a/drivers/md/dm-crypt.c
> +++ b/drivers/md/dm-crypt.c
> @@ -1674,6 +1674,8 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned int size)
>  		if (!pages) {
>  			crypt_free_buffer_pages(cc, clone);
>  			bio_put(clone);
> +			if (unlikely(gfp_mask & __GFP_DIRECT_RECLAIM))
> +				mutex_unlock(&cc->bio_alloc_lock);
>  			gfp_mask |= __GFP_DIRECT_RECLAIM;
>  			order = 0;
>  			goto retry;
> -- 
> 2.34.1
> 


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-08-10  9:46 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-09  5:18 [PATCH] dm-crypt: unlock allocation mutex before retry Runyu Xiao
2026-08-09 13:20 ` Bart Van Assche
2026-08-10  9:46 ` Mikulas Patocka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox