FAILED: Patch "dm: clear cloned request bio pointer when last clone bio completes" failed to apply to 6.1-stable tree
Subsystems (2)
Sasha Levin
maintainerThe patch below does not apply to the 6.1-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
Thanks,
Sasha
------------------ original commit in Linus's tree ------------------
From fb8a6c18fb9a6561f7a15b58b272442b77a242dd Mon Sep 17 00:00:00 2001
From: Michael Liang <[email protected]>
Date: Fri, 9 Jan 2026 15:52:54 -0700
Subject: [PATCH] dm: clear cloned request bio pointer when last clone bio
completes
Stale rq->bio values have been observed to cause double-initialization of cloned bios in request-based device-mapper targets, leading to use-after-free and double-free scenarios.
One such case occurs when using dm-multipath on top of a PCIe NVMe namespace, where cloned request bios are freed during blk_complete_request(), but rq->bio is left intact. Subsequent clone teardown then attempts to free the same bios again via blk_rq_unprep_clone().
The resulting double-free path looks like:
nvme_pci_complete_batch()
nvme_complete_batch()
blk_mq_end_request_batch()
blk_complete_request() // called on a DM clone request
bio_endio() // first free of all clone bios
...
rq->end_io() // end_clone_request()
dm_complete_request(tio->orig)
dm_softirq_done()
dm_done()
dm_end_request()
blk_rq_unprep_clone() // second free of clone biosFix this by clearing the clone request's bio pointer when the last cloned bio completes, ensuring that later teardown paths do not attempt to free already-released bios.
--- drivers/md/dm-rq.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
drivers/md/dm-rq.c +10 -3
@@ -109,14 +109,21 @@ static void end_clone_bio(struct bio *clone)*/ tio->completed += nr_bytes; +if (!is_last) +return ; +/* +* At this moment we know this is the last bio of the cloned request, +* and all cloned bios have been released, so reset the clone request's +* bio pointer to avoid double free. +*/ + tio->clone->bio =NULL ; + exit:/* * Update the original request. * Do not use blk_mq_end_request() here, because it may complete * the original request before the clone, and break the ordering. */ -if (is_last) - exit: -blk_update_request (tio->orig,BLK_STS_OK , tio->completed); +blk_update_request (tio->orig,BLK_STS_OK , tio->completed); }static struct dm_rq_target_io *tio_from_request (struct request *rq)
Signature · 1 line
2.51.0