]> Git Repo - linux.git/commitdiff
bcachefs; guard against overflow in btree node split
authorKent Overstreet <[email protected]>
Mon, 18 Dec 2023 04:31:26 +0000 (23:31 -0500)
committerKent Overstreet <[email protected]>
Tue, 19 Dec 2023 21:18:16 +0000 (16:18 -0500)
Signed-off-by: Kent Overstreet <[email protected]>
fs/bcachefs/btree_update_interior.c

index 19fa160238eaed76216334cacfc3b52291ee6653..239fcc3c7c996c960eed57f5c8ec01322f279748 100644 (file)
@@ -1346,8 +1346,11 @@ static void __btree_split_node(struct btree_update *as,
        struct bkey_packed *out[2];
        struct bkey uk;
        unsigned u64s, n1_u64s = (b->nr.live_u64s * 3) / 5;
+       struct { unsigned nr_keys, val_u64s; } nr_keys[2];
        int i;
 
+       memset(&nr_keys, 0, sizeof(nr_keys));
+
        for (i = 0; i < 2; i++) {
                BUG_ON(n[i]->nsets != 1);
 
@@ -1369,6 +1372,9 @@ static void __btree_split_node(struct btree_update *as,
                if (!i)
                        n1_pos = uk.p;
                bch2_bkey_format_add_key(&format[i], &uk);
+
+               nr_keys[i].nr_keys++;
+               nr_keys[i].val_u64s += bkeyp_val_u64s(&b->format, k);
        }
 
        btree_set_min(n[0], b->data->min_key);
@@ -1381,6 +1387,12 @@ static void __btree_split_node(struct btree_update *as,
                bch2_bkey_format_add_pos(&format[i], n[i]->data->max_key);
 
                n[i]->data->format = bch2_bkey_format_done(&format[i]);
+
+               unsigned u64s = nr_keys[i].nr_keys * n[i]->data->format.key_u64s +
+                       nr_keys[i].val_u64s;
+               if (__vstruct_bytes(struct btree_node, u64s) > btree_bytes(as->c))
+                       n[i]->data->format = b->format;
+
                btree_node_set_format(n[i], n[i]->data->format);
        }
 
This page took 0.05946 seconds and 4 git commands to generate.