bcachefs: fix unsafety in bch2_stripe_to_text()
authorKent Overstreet <kent.overstreet@linux.dev>
Fri, 12 Apr 2024 03:37:24 +0000 (23:37 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 14 Apr 2024 02:48:16 +0000 (22:48 -0400)
.to_text() functions need to work on key values that didn't pass .valid

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

index 082075244e16aedc824249b239ecec6efb1a07fa..c0b2b2f180e014da5e2252e1fdd50e9ac8081aa0 100644 (file)
@@ -131,29 +131,33 @@ fsck_err:
 void bch2_stripe_to_text(struct printbuf *out, struct bch_fs *c,
                         struct bkey_s_c k)
 {
-       const struct bch_stripe *s = bkey_s_c_to_stripe(k).v;
-       unsigned i, nr_data = s->nr_blocks - s->nr_redundant;
+       const struct bch_stripe *sp = bkey_s_c_to_stripe(k).v;
+       struct bch_stripe s = {};
+
+       memcpy(&s, sp, min(sizeof(s), bkey_val_bytes(k.k)));
+
+       unsigned nr_data = s.nr_blocks - s.nr_redundant;
 
        prt_printf(out, "algo %u sectors %u blocks %u:%u csum %u gran %u",
-              s->algorithm,
-              le16_to_cpu(s->sectors),
-              nr_data,
-              s->nr_redundant,
-              s->csum_type,
-              1U << s->csum_granularity_bits);
-
-       for (i = 0; i < s->nr_blocks; i++) {
-               const struct bch_extent_ptr *ptr = s->ptrs + i;
-               struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev);
-               u32 offset;
-               u64 b = sector_to_bucket_and_offset(ca, ptr->offset, &offset);
-
-               prt_printf(out, " %u:%llu:%u", ptr->dev, b, offset);
-               if (i < nr_data)
-                       prt_printf(out, "#%u", stripe_blockcount_get(s, i));
-               prt_printf(out, " gen %u", ptr->gen);
-               if (ptr_stale(ca, ptr))
-                       prt_printf(out, " stale");
+                  s.algorithm,
+                  le16_to_cpu(s.sectors),
+                  nr_data,
+                  s.nr_redundant,
+                  s.csum_type,
+                  1U << s.csum_granularity_bits);
+
+       for (unsigned i = 0; i < s.nr_blocks; i++) {
+               const struct bch_extent_ptr *ptr = sp->ptrs + i;
+
+               if ((void *) ptr >= bkey_val_end(k))
+                       break;
+
+               bch2_extent_ptr_to_text(out, c, ptr);
+
+               if (s.csum_type < BCH_CSUM_NR &&
+                   i < nr_data &&
+                   stripe_blockcount_offset(&s, i) < bkey_val_bytes(k.k))
+                       prt_printf(out,  "#%u", stripe_blockcount_get(sp, i));
        }
 }
 
index f4369b02e805f0a24572a8cf87d18867c3d3301a..f042616888b0a1d47d7797e987c912c58d0945b3 100644 (file)
@@ -32,6 +32,8 @@ static inline unsigned stripe_csums_per_device(const struct bch_stripe *s)
 static inline unsigned stripe_csum_offset(const struct bch_stripe *s,
                                          unsigned dev, unsigned csum_idx)
 {
+       EBUG_ON(s->csum_type >= BCH_CSUM_NR);
+
        unsigned csum_bytes = bch_crc_bytes[s->csum_type];
 
        return sizeof(struct bch_stripe) +