]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
btrfs: check for NULL root after calls to btrfs_csum_root()
authorFilipe Manana <fdmanana@suse.com>
Sun, 8 Feb 2026 19:43:01 +0000 (19:43 +0000)
committerDavid Sterba <dsterba@suse.com>
Tue, 17 Mar 2026 10:29:32 +0000 (11:29 +0100)
btrfs_csum_root() can return a NULL pointer in case the root we are
looking for is not in the rb tree that tracks roots. So add checks to
every caller that is missing such check to log a message and return
an error.

Reported-by: Chris Mason <clm@meta.com>
Link: https://lore.kernel.org/linux-btrfs/20260208161657.3972997-1-clm@meta.com/
Reviewed-by: Boris Burkov <boris@bur.io>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/file-item.c
fs/btrfs/inode.c
fs/btrfs/raid56.c
fs/btrfs/relocation.c
fs/btrfs/tree-log.c

index 08368247668e3c41df6be3c2a2cf7768c29a80ad..b1b53d713ee94bd3b74bef9275c526e5f4b8cc6d 100644 (file)
@@ -1627,6 +1627,10 @@ static int backup_super_roots(struct btrfs_fs_info *info)
                        btrfs_err(info, "missing extent root for extent at bytenr 0");
                        return -EUCLEAN;
                }
+               if (unlikely(!csum_root)) {
+                       btrfs_err(info, "missing csum root for extent at bytenr 0");
+                       return -EUCLEAN;
+               }
 
                btrfs_set_backup_extent_root(root_backup,
                                             extent_root->node->start);
index 7fcd83f32014a1f6f71df664c0360a608bf23424..85ee5c79759d8f6c9e0d88ef35417838f47b740d 100644 (file)
@@ -1974,8 +1974,15 @@ static int cleanup_ref_head(struct btrfs_trans_handle *trans,
                        struct btrfs_root *csum_root;
 
                        csum_root = btrfs_csum_root(fs_info, head->bytenr);
-                       ret = btrfs_del_csums(trans, csum_root, head->bytenr,
-                                             head->num_bytes);
+                       if (unlikely(!csum_root)) {
+                               btrfs_err(fs_info,
+                                         "missing csum root for extent at bytenr %llu",
+                                         head->bytenr);
+                               ret = -EUCLEAN;
+                       } else {
+                               ret = btrfs_del_csums(trans, csum_root, head->bytenr,
+                                                     head->num_bytes);
+                       }
                }
        }
 
@@ -3147,6 +3154,15 @@ static int do_free_extent_accounting(struct btrfs_trans_handle *trans,
                struct btrfs_root *csum_root;
 
                csum_root = btrfs_csum_root(trans->fs_info, bytenr);
+               if (unlikely(!csum_root)) {
+                       ret = -EUCLEAN;
+                       btrfs_abort_transaction(trans, ret);
+                       btrfs_err(trans->fs_info,
+                                 "missing csum root for extent at bytenr %llu",
+                                 bytenr);
+                       return ret;
+               }
+
                ret = btrfs_del_csums(trans, csum_root, bytenr, num_bytes);
                if (unlikely(ret)) {
                        btrfs_abort_transaction(trans, ret);
index 7bd715442f3ee64952173e81009e43a73f10c62e..f585ddfa8440fea99e50889f98382ba622da8c98 100644 (file)
@@ -308,6 +308,13 @@ static int search_csum_tree(struct btrfs_fs_info *fs_info,
        /* Current item doesn't contain the desired range, search again */
        btrfs_release_path(path);
        csum_root = btrfs_csum_root(fs_info, disk_bytenr);
+       if (unlikely(!csum_root)) {
+               btrfs_err(fs_info,
+                         "missing csum root for extent at bytenr %llu",
+                         disk_bytenr);
+               return -EUCLEAN;
+       }
+
        item = btrfs_lookup_csum(NULL, csum_root, path, disk_bytenr, 0);
        if (IS_ERR(item)) {
                ret = PTR_ERR(item);
index b409efe1857e1511f4ab28ccffa11e5bccac22bb..ed4d19780f22af3d7f538975561f0a6b94b7ec97 100644 (file)
@@ -2012,6 +2012,13 @@ static int can_nocow_file_extent(struct btrfs_path *path,
         */
 
        csum_root = btrfs_csum_root(root->fs_info, io_start);
+       if (unlikely(!csum_root)) {
+               btrfs_err(root->fs_info,
+                         "missing csum root for extent at bytenr %llu", io_start);
+               ret = -EUCLEAN;
+               goto out;
+       }
+
        ret = btrfs_lookup_csums_list(csum_root, io_start,
                                      io_start + args->file_extent.num_bytes - 1,
                                      NULL, nowait);
@@ -2749,10 +2756,17 @@ static int add_pending_csums(struct btrfs_trans_handle *trans,
        int ret;
 
        list_for_each_entry(sum, list, list) {
-               trans->adding_csums = true;
-               if (!csum_root)
+               if (!csum_root) {
                        csum_root = btrfs_csum_root(trans->fs_info,
                                                    sum->logical);
+                       if (unlikely(!csum_root)) {
+                               btrfs_err(trans->fs_info,
+                                 "missing csum root for extent at bytenr %llu",
+                                         sum->logical);
+                               return -EUCLEAN;
+                       }
+               }
+               trans->adding_csums = true;
                ret = btrfs_csum_file_blocks(trans, csum_root, sum);
                trans->adding_csums = false;
                if (ret)
index baadaaa189c05d968b3b63687bce5dabdf116939..230dd93dad6e5499fd4d8bb0d137f917245001b5 100644 (file)
@@ -2295,8 +2295,7 @@ void raid56_parity_recover(struct bio *bio, struct btrfs_io_context *bioc,
 static void fill_data_csums(struct btrfs_raid_bio *rbio)
 {
        struct btrfs_fs_info *fs_info = rbio->bioc->fs_info;
-       struct btrfs_root *csum_root = btrfs_csum_root(fs_info,
-                                                      rbio->bioc->full_stripe_logical);
+       struct btrfs_root *csum_root;
        const u64 start = rbio->bioc->full_stripe_logical;
        const u32 len = (rbio->nr_data * rbio->stripe_nsectors) <<
                        fs_info->sectorsize_bits;
@@ -2329,6 +2328,15 @@ static void fill_data_csums(struct btrfs_raid_bio *rbio)
                goto error;
        }
 
+       csum_root = btrfs_csum_root(fs_info, rbio->bioc->full_stripe_logical);
+       if (unlikely(!csum_root)) {
+               btrfs_err(fs_info,
+                         "missing csum root for extent at bytenr %llu",
+                         rbio->bioc->full_stripe_logical);
+               ret = -EUCLEAN;
+               goto error;
+       }
+
        ret = btrfs_lookup_csums_bitmap(csum_root, NULL, start, start + len - 1,
                                        rbio->csum_buf, rbio->csum_bitmap);
        if (ret < 0)
index 93a5ae23406df4a550eaa4799cb66cddba36e245..2625a66054d06be1cf05b50a3a2b5ff0c57c7113 100644 (file)
@@ -5654,6 +5654,14 @@ int btrfs_reloc_clone_csums(struct btrfs_ordered_extent *ordered)
        LIST_HEAD(list);
        int ret;
 
+       if (unlikely(!csum_root)) {
+               btrfs_mark_ordered_extent_error(ordered);
+               btrfs_err(fs_info,
+                         "missing csum root for extent at bytenr %llu",
+                         disk_bytenr);
+               return -EUCLEAN;
+       }
+
        ret = btrfs_lookup_csums_list(csum_root, disk_bytenr,
                                      disk_bytenr + ordered->num_bytes - 1,
                                      &list, false);
index 37c272df52b05fb327d7664ad5da88c2b5a1a05f..9ff3933bc38204bcadff0733df8428e2543cd756 100644 (file)
@@ -984,6 +984,13 @@ static noinline int replay_one_extent(struct walk_control *wc)
 
                sums = list_first_entry(&ordered_sums, struct btrfs_ordered_sum, list);
                csum_root = btrfs_csum_root(fs_info, sums->logical);
+               if (unlikely(!csum_root)) {
+                       btrfs_err(fs_info,
+                                 "missing csum root for extent at bytenr %llu",
+                                 sums->logical);
+                       ret = -EUCLEAN;
+               }
+
                if (!ret) {
                        ret = btrfs_del_csums(trans, csum_root, sums->logical,
                                              sums->len);
@@ -4890,6 +4897,13 @@ static noinline int copy_items(struct btrfs_trans_handle *trans,
                }
 
                csum_root = btrfs_csum_root(trans->fs_info, disk_bytenr);
+               if (unlikely(!csum_root)) {
+                       btrfs_err(trans->fs_info,
+                                 "missing csum root for extent at bytenr %llu",
+                                 disk_bytenr);
+                       return -EUCLEAN;
+               }
+
                disk_bytenr += extent_offset;
                ret = btrfs_lookup_csums_list(csum_root, disk_bytenr,
                                              disk_bytenr + extent_num_bytes - 1,
@@ -5086,6 +5100,13 @@ static int log_extent_csums(struct btrfs_trans_handle *trans,
        /* block start is already adjusted for the file extent offset. */
        block_start = btrfs_extent_map_block_start(em);
        csum_root = btrfs_csum_root(trans->fs_info, block_start);
+       if (unlikely(!csum_root)) {
+               btrfs_err(trans->fs_info,
+                         "missing csum root for extent at bytenr %llu",
+                         block_start);
+               return -EUCLEAN;
+       }
+
        ret = btrfs_lookup_csums_list(csum_root, block_start + csum_offset,
                                      block_start + csum_offset + csum_len - 1,
                                      &ordered_sums, false);