]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
btrfs: do not clean up repair bio if submit fails
authorJosef Bacik <josef@toxicpanda.com>
Tue, 23 Dec 2025 08:00:41 +0000 (08:00 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 19 Jan 2026 12:12:06 +0000 (13:12 +0100)
[ Upstream commit 8cbc3001a3264d998d6b6db3e23f935c158abd4d ]

The submit helper will always run bio_endio() on the bio if it fails to
submit, so cleaning up the bio just leads to a variety of use-after-free
and NULL pointer dereference bugs because we race with the endio
function that is cleaning up the bio.  Instead just return BLK_STS_OK as
the repair function has to continue to process the rest of the pages,
and the endio for the repair bio will do the appropriate cleanup for the
page that it was given.

Reviewed-by: Boris Burkov <boris@bur.io>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: David Sterba <dsterba@suse.com>
[Minor context change fixed.]
Signed-off-by: Bin Lan <bin.lan.cn@windriver.com>
Signed-off-by: He Zhe <zhe.he@windriver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[ Keerthana: Backported the patch to v5.10.y ]
Signed-off-by: Keerthana K <keerthana.kalyanasundaram@broadcom.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/btrfs/extent_io.c

index 489d370ddd6070cd4f84227beecf04d542b85e6d..3d0b854e0c19d6dc2852f0f1b827492f455179de 100644 (file)
@@ -2655,7 +2655,6 @@ blk_status_t btrfs_submit_read_repair(struct inode *inode,
        bool need_validation;
        struct bio *repair_bio;
        struct btrfs_io_bio *repair_io_bio;
-       blk_status_t status;
 
        btrfs_debug(fs_info,
                   "repair read error: read error at %llu", start);
@@ -2699,13 +2698,13 @@ blk_status_t btrfs_submit_read_repair(struct inode *inode,
 "repair read error: submitting new read to mirror %d, in_validation=%d",
                    failrec->this_mirror, failrec->in_validation);
 
-       status = submit_bio_hook(inode, repair_bio, failrec->this_mirror,
-                                failrec->bio_flags);
-       if (status) {
-               free_io_failure(failure_tree, tree, failrec);
-               bio_put(repair_bio);
-       }
-       return status;
+       /*
+        * At this point we have a bio, so any errors from submit_bio_hook()
+        * will be handled by the endio on the repair_bio, so we can't return an
+        * error here.
+        */
+       submit_bio_hook(inode, repair_bio, failrec->this_mirror, failrec->bio_flags);
+       return BLK_STS_OK;
 }
 
 /* lots and lots of room for performance fixes in the end_bio funcs */