Skip to content

Commit

Permalink
btrfs: do not clean up repair bio if submit fails
Browse files Browse the repository at this point in the history
commit 8cbc300 upstream.

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>
  • Loading branch information
Josef Bacik authored and Greg Kroah-Hartman committed May 22, 2025
1 parent d64807d commit 7170875
Showing 1 changed file with 7 additions and 8 deletions.
15 changes: 7 additions & 8 deletions fs/btrfs/extent_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -2624,7 +2624,6 @@ int btrfs_repair_one_sector(struct inode *inode,
const int icsum = bio_offset >> fs_info->sectorsize_bits;
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);
Expand Down Expand Up @@ -2664,13 +2663,13 @@ int btrfs_repair_one_sector(struct inode *inode,
"repair read error: submitting new read to mirror %d",
failrec->this_mirror);

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 blk_status_to_errno(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;
}

static void end_page_read(struct page *page, bool uptodate, u64 start, u32 len)
Expand Down

0 comments on commit 7170875

Please sign in to comment.