[PATCH] dm-crypt: unlock allocation mutex before retry

Runyu Xiao <[email protected]>
Newsgroups dev.linux.lists.dm-devel,org.kernel.vger.linux-kernel,org.kernel.vger.stable
Message-ID <[email protected]>
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: [email protected]
Signed-off-by: Runyu Xiao <[email protected]>
---
 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.