bcachefs: Fix missing validation for bch_backpointer.level
authorKent Overstreet <kent.overstreet@linux.dev>
Fri, 8 Nov 2024 03:18:02 +0000 (22:18 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Fri, 8 Nov 2024 05:05:53 +0000 (00:05 -0500)
This fixes an assertion pop where we try to navigate to the target of
the backpointer, and the path level isn't what we expect.

Reported-by: syzbot+b17df21b4d370f2dc330@syzkaller.appspotmail.com
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/backpointers.c
fs/bcachefs/sb-errors_format.h

index 47455a85c90924ce9daa32556f0df9f15d00f19c..ed344400c8bdcf8355ea2d5b6b98392fd84b7cab 100644 (file)
@@ -52,6 +52,12 @@ int bch2_backpointer_validate(struct bch_fs *c, struct bkey_s_c k,
                              enum bch_validate_flags flags)
 {
        struct bkey_s_c_backpointer bp = bkey_s_c_to_backpointer(k);
+       int ret = 0;
+
+       bkey_fsck_err_on(bp.v->level > BTREE_MAX_DEPTH,
+                        c, backpointer_level_bad,
+                        "backpointer level bad: %u >= %u",
+                        bp.v->level, BTREE_MAX_DEPTH);
 
        rcu_read_lock();
        struct bch_dev *ca = bch2_dev_rcu_noerror(c, bp.k->p.inode);
@@ -64,7 +70,6 @@ int bch2_backpointer_validate(struct bch_fs *c, struct bkey_s_c k,
        struct bpos bucket = bp_pos_to_bucket(ca, bp.k->p);
        struct bpos bp_pos = bucket_pos_to_bp_noerror(ca, bucket, bp.v->bucket_offset);
        rcu_read_unlock();
-       int ret = 0;
 
        bkey_fsck_err_on((bp.v->bucket_offset >> MAX_EXTENT_COMPRESS_RATIO_SHIFT) >= ca->mi.bucket_size ||
                         !bpos_eq(bp.k->p, bp_pos),
index 937275d061fe0c0bee6deadb6e062f39ff0adfa7..9feb6739f77a1c869686715557703f80f55c7d57 100644 (file)
@@ -136,7 +136,9 @@ enum bch_fsck_flags {
        x(bucket_gens_nonzero_for_invalid_buckets,              122,    FSCK_AUTOFIX)   \
        x(need_discard_freespace_key_to_invalid_dev_bucket,     123,    0)              \
        x(need_discard_freespace_key_bad,                       124,    0)              \
+       x(discarding_bucket_not_in_need_discard_btree,          291,    0)              \
        x(backpointer_bucket_offset_wrong,                      125,    0)              \
+       x(backpointer_level_bad,                                294,    0)              \
        x(backpointer_to_missing_device,                        126,    0)              \
        x(backpointer_to_missing_alloc,                         127,    0)              \
        x(backpointer_to_missing_ptr,                           128,    0)              \
@@ -177,7 +179,9 @@ enum bch_fsck_flags {
        x(ptr_stripe_redundant,                                 163,    0)              \
        x(reservation_key_nr_replicas_invalid,                  164,    0)              \
        x(reflink_v_refcount_wrong,                             165,    0)              \
+       x(reflink_v_pos_bad,                                    292,    0)              \
        x(reflink_p_to_missing_reflink_v,                       166,    0)              \
+       x(reflink_refcount_underflow,                           293,    0)              \
        x(stripe_pos_bad,                                       167,    0)              \
        x(stripe_val_size_bad,                                  168,    0)              \
        x(stripe_csum_granularity_bad,                          290,    0)              \
@@ -302,7 +306,7 @@ enum bch_fsck_flags {
        x(accounting_key_replicas_devs_unsorted,                280,    FSCK_AUTOFIX)   \
        x(accounting_key_version_0,                             282,    FSCK_AUTOFIX)   \
        x(logged_op_but_clean,                                  283,    FSCK_AUTOFIX)   \
-       x(MAX,                                                  291,    0)
+       x(MAX,                                                  295,    0)
 
 enum bch_sb_error_id {
 #define x(t, n, ...) BCH_FSCK_ERR_##t = n,