summaryrefslogtreecommitdiffstats
path: root/fs/bcachefs/super-io.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2025-03-17 13:58:51 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2025-03-24 09:50:35 -0400
commit92c7789a9ed892da60cb5da2bcb6278551e2eb34 (patch)
treea7d8d35d53debb2a65d8b6a080e14f256efc3358 /fs/bcachefs/super-io.c
parentbcachefs: bch2_sb_validate() doesn't need bch_sb_handle (diff)
downloadlinux-92c7789a9ed892da60cb5da2bcb6278551e2eb34.tar.gz
linux-92c7789a9ed892da60cb5da2bcb6278551e2eb34.zip
bcachefs: Validate bch_sb.offset field
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>
Diffstat (limited to 'fs/bcachefs/super-io.c')
-rw-r--r--fs/bcachefs/super-io.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/fs/bcachefs/super-io.c b/fs/bcachefs/super-io.c
index 2e86a04b49e0..f2e4428281a3 100644
--- a/fs/bcachefs/super-io.c
+++ b/fs/bcachefs/super-io.c
@@ -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;