bcachefs: Correctly validate k->u64s in btree node read path
authorKent Overstreet <kent.overstreet@linux.dev>
Fri, 8 Mar 2024 19:53:03 +0000 (14:53 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 10 Mar 2024 19:21:04 +0000 (15:21 -0400)
validate_bset_keys() never properly validated k->u64s; it checked if it
was 0, but not if it was smaller than keys for the given packed format;
this fixes that small oversight.

This patch was backported, so it's adding quite a few error enums so
that they don't get renumbered and we don't have confusing gaps.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/bkey.h
fs/bcachefs/btree_io.c
fs/bcachefs/sb-errors_types.h

index 831be01809f2c9271d4db159377decd1b8686bb6..2a8b8fef539c7d80d3a9a57fc9e72c59937ace5b 100644 (file)
@@ -362,10 +362,7 @@ static inline struct bpos bkey_start_pos(const struct bkey *k)
 static inline unsigned bkeyp_key_u64s(const struct bkey_format *format,
                                      const struct bkey_packed *k)
 {
-       unsigned ret = bkey_packed(k) ? format->key_u64s : BKEY_U64s;
-
-       EBUG_ON(k->u64s < ret);
-       return ret;
+       return bkey_packed(k) ? format->key_u64s : BKEY_U64s;
 }
 
 static inline unsigned bkeyp_key_bytes(const struct bkey_format *format,
index aa9b6cbe3226909626411b886731a8bb8648a558..caf3eecfc801e902bd8ec2b589bff05a5cb0d3bf 100644 (file)
@@ -840,6 +840,9 @@ static bool __bkey_valid(struct bch_fs *c, struct btree *b,
        if (k->format > KEY_FORMAT_CURRENT)
                return false;
 
+       if (k->u64s < bkeyp_key_u64s(&b->format, k))
+               return false;
+
        struct printbuf buf = PRINTBUF;
        struct bkey tmp;
        struct bkey_s u = __bkey_disassemble(b, k, &tmp);
@@ -881,7 +884,13 @@ static int validate_bset_keys(struct bch_fs *c, struct btree *b,
                                 "invalid bkey format %u", k->format))
                        goto drop_this_key;
 
-               /* XXX: validate k->u64s */
+               if (btree_err_on(k->u64s < bkeyp_key_u64s(&b->format, k),
+                                -BCH_ERR_btree_node_read_err_fixable,
+                                c, NULL, b, i,
+                                btree_node_bkey_bad_u64s,
+                                "k->u64s too small (%u < %u)", k->u64s, bkeyp_key_u64s(&b->format, k)))
+                       goto drop_this_key;
+
                if (!write)
                        bch2_bkey_compat(b->c.level, b->c.btree_id, version,
                                    BSET_BIG_ENDIAN(i), write,
index c08aacdfd073c203e44a072363c94e89dd93eec8..2c998e721d90011d4e84a2306d29246f138de1cc 100644 (file)
        x(hash_table_key_duplicate,                             242)    \
        x(hash_table_key_wrong_offset,                          243)    \
        x(unlinked_inode_not_on_deleted_list,                   244)    \
-       x(reflink_p_front_pad_bad,                              245)
+       x(reflink_p_front_pad_bad,                              245)    \
+       x(journal_entry_dup_same_device,                        246)    \
+       x(inode_bi_subvol_missing,                              247)    \
+       x(inode_bi_subvol_wrong,                                248)    \
+       x(inode_points_to_missing_dirent,                       249)    \
+       x(inode_points_to_wrong_dirent,                         250)    \
+       x(inode_bi_parent_nonzero,                              251)    \
+       x(dirent_to_missing_parent_subvol,                      252)    \
+       x(dirent_not_visible_in_parent_subvol,                  253)    \
+       x(subvol_fs_path_parent_wrong,                          254)    \
+       x(subvol_root_fs_path_parent_nonzero,                   255)    \
+       x(subvol_children_not_set,                              256)    \
+       x(subvol_children_bad,                                  257)    \
+       x(subvol_loop,                                          258)    \
+       x(subvol_unreachable,                                   259)    \
+       x(btree_node_bkey_bad_u64s,                             260)
 
 enum bch_sb_error_id {
 #define x(t, n) BCH_FSCK_ERR_##t = n,