bcachefs: Check that keys are in the correct btrees
authorKent Overstreet <kent.overstreet@gmail.com>
Sun, 18 Apr 2021 03:18:17 +0000 (23:18 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:01 +0000 (17:09 -0400)
We've started seeing bug reports of pointers to btree nodes being
detected in leaf nodes. This should catch that before it's happened, and
it's something we should've been checking anyways.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/bkey_methods.c

index 6fe95b802e130060b48caa6ad54b2f2c38620c9b..cf2e054cca2f75c63f677528bfcd3148a5bc8889 100644 (file)
@@ -98,12 +98,51 @@ const char *bch2_bkey_val_invalid(struct bch_fs *c, struct bkey_s_c k)
        return bch2_bkey_ops[k.k->type].key_invalid(c, k);
 }
 
+static unsigned bch2_key_types_allowed[] = {
+       [BKEY_TYPE_extents] =
+               (1U << KEY_TYPE_error)|
+               (1U << KEY_TYPE_cookie)|
+               (1U << KEY_TYPE_extent)|
+               (1U << KEY_TYPE_reservation)|
+               (1U << KEY_TYPE_reflink_p)|
+               (1U << KEY_TYPE_inline_data),
+       [BKEY_TYPE_inodes] =
+               (1U << KEY_TYPE_inode)|
+               (1U << KEY_TYPE_inode_generation),
+       [BKEY_TYPE_dirents] =
+               (1U << KEY_TYPE_hash_whiteout)|
+               (1U << KEY_TYPE_dirent),
+       [BKEY_TYPE_xattrs] =
+               (1U << KEY_TYPE_cookie)|
+               (1U << KEY_TYPE_hash_whiteout)|
+               (1U << KEY_TYPE_xattr),
+       [BKEY_TYPE_alloc] =
+               (1U << KEY_TYPE_alloc)|
+               (1U << KEY_TYPE_alloc_v2),
+       [BKEY_TYPE_quotas] =
+               (1U << KEY_TYPE_quota),
+       [BKEY_TYPE_stripes] =
+               (1U << KEY_TYPE_stripe),
+       [BKEY_TYPE_reflink] =
+               (1U << KEY_TYPE_reflink_v)|
+               (1U << KEY_TYPE_indirect_inline_data),
+       [BKEY_TYPE_btree] =
+               (1U << KEY_TYPE_btree_ptr)|
+               (1U << KEY_TYPE_btree_ptr_v2),
+};
+
 const char *__bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k,
                                enum btree_node_type type)
 {
+       unsigned key_types_allowed = (1U << KEY_TYPE_deleted)|
+               bch2_key_types_allowed[type] ;
+
        if (k.k->u64s < BKEY_U64s)
                return "u64s too small";
 
+       if (!(key_types_allowed & (1U << k.k->type)))
+               return "invalid key type for this btree";
+
        if (type == BKEY_TYPE_btree &&
            bkey_val_u64s(k.k) > BKEY_BTREE_PTR_VAL_U64s_MAX)
                return "value too big";