]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
bcachefs: Validate bch_sb.offset field
authorKent Overstreet <kent.overstreet@linux.dev>
Mon, 17 Mar 2025 17:58:51 +0000 (13:58 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Mon, 24 Mar 2025 13:50:35 +0000 (09:50 -0400)
This was missed - but it needs to be correct for the superblock recovery
tool that scans the start and end of the device for backup superblocks:
we don't want to pick up superblocks that belong to a different
partition that starts at a different offset.

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

index 493cae4efc3757ba0e00de624b0e9c910b6b2916..cb27de6ffad69e318d333c905eda63e67000c755 100644 (file)
        x(BCH_ERR_invalid_sb,           invalid_sb_csum)                        \
        x(BCH_ERR_invalid_sb,           invalid_sb_block_size)                  \
        x(BCH_ERR_invalid_sb,           invalid_sb_uuid)                        \
+       x(BCH_ERR_invalid_sb,           invalid_sb_offset)                      \
        x(BCH_ERR_invalid_sb,           invalid_sb_too_many_members)            \
        x(BCH_ERR_invalid_sb,           invalid_sb_dev_idx)                     \
        x(BCH_ERR_invalid_sb,           invalid_sb_time_precision)              \
index 2e86a04b49e0ac22bf18460f6f9a8d8d836376d8..f2e4428281a3e16764be5e242136e1e4e22b5132 100644 (file)
@@ -365,7 +365,8 @@ static int bch2_sb_compatible(struct bch_sb *sb, struct printbuf *out)
        return 0;
 }
 
-int bch2_sb_validate(struct bch_sb *sb, enum bch_validate_flags flags, struct printbuf *out)
+int bch2_sb_validate(struct bch_sb *sb, u64 read_offset,
+                    enum bch_validate_flags flags, struct printbuf *out)
 {
        struct bch_sb_field_members_v1 *mi;
        enum bch_opt_id opt_id;
@@ -409,6 +410,13 @@ int bch2_sb_validate(struct bch_sb *sb, enum bch_validate_flags flags, struct pr
                return -BCH_ERR_invalid_sb_uuid;
        }
 
+       if (!(flags & BCH_VALIDATE_write) &&
+           le64_to_cpu(sb->offset) != read_offset) {
+               prt_printf(out, "Bad sb offset (got %llu, read from %llu)",
+                          le64_to_cpu(sb->offset), read_offset);
+               return -BCH_ERR_invalid_sb_offset;
+       }
+
        if (!sb->nr_devices ||
            sb->nr_devices > BCH_SB_MEMBERS_MAX) {
                prt_printf(out, "Bad number of member devices %u (max %u)",
@@ -888,7 +896,7 @@ got_super:
 
        sb->have_layout = true;
 
-       ret = bch2_sb_validate(sb->sb, 0, &err);
+       ret = bch2_sb_validate(sb->sb, offset, 0, &err);
        if (ret) {
                bch2_print_opts(opts, KERN_ERR "bcachefs (%s): error validating superblock: %s\n",
                                path, err.buf);
@@ -1045,7 +1053,7 @@ int bch2_write_super(struct bch_fs *c)
        darray_for_each(online_devices, ca) {
                printbuf_reset(&err);
 
-               ret = bch2_sb_validate((*ca)->disk_sb.sb, BCH_VALIDATE_write, &err);
+               ret = bch2_sb_validate((*ca)->disk_sb.sb, 0, BCH_VALIDATE_write, &err);
                if (ret) {
                        bch2_fs_inconsistent(c, "sb invalid before write: %s", err.buf);
                        goto out;
index 41562380a353e625b04a4a46e632d757a6df2f65..78f708a6fbcdfb5bdf8302ae6abf9be9c1613291 100644 (file)
@@ -92,7 +92,7 @@ int bch2_sb_from_fs(struct bch_fs *, struct bch_dev *);
 void bch2_free_super(struct bch_sb_handle *);
 int bch2_sb_realloc(struct bch_sb_handle *, unsigned);
 
-int bch2_sb_validate(struct bch_sb *, enum bch_validate_flags, struct printbuf *);
+int bch2_sb_validate(struct bch_sb *, u64, enum bch_validate_flags, struct printbuf *);
 
 int bch2_read_super(const char *, struct bch_opts *, struct bch_sb_handle *);
 int bch2_read_super_silent(const char *, struct bch_opts *, struct bch_sb_handle *);