]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libblkid: (bcachefs) fix not detecting large superblocks
authorColin Gillespie <colin@cgillespie.xyz>
Wed, 9 Aug 2023 08:28:07 +0000 (18:28 +1000)
committerColin Gillespie <colin@cgillespie.xyz>
Thu, 10 Aug 2023 05:52:23 +0000 (15:52 +1000)
Probing does not detect bcachefs filesystems with a superblock larger
than 4KiB. Bcachefs superblocks grow in size and can become much larger
than this.

Increase the superblock maximum size limit to 1MiB.

Validate the superblock isn't larger than the maximum size defined in
the superblocks layout section.

libblkid/src/superblocks/bcache.c

index 1a0c124d374f0c4fa222f0b3d198d93c1619d604..2b0f6fc688101b92c6708b9a1f59833d05f79530 100644 (file)
@@ -103,6 +103,15 @@ union bcachefs_sb_csum {
        uint8_t raw[16];
 } __attribute__((packed));
 
+struct bcachefs_sb_layout {
+       uint8_t         magic[16];
+       uint8_t         layout_type;
+       uint8_t         sb_max_size_bits;
+       uint8_t         nr_superblocks;
+       uint8_t         pad[5];
+       uint64_t        sb_offset[61];
+} __attribute__((packed));
+
 struct bcachefs_super_block {
        union bcachefs_sb_csum  csum;
        uint16_t        version;
@@ -124,7 +133,7 @@ struct bcachefs_super_block {
        uint64_t        flags[8];
        uint64_t        features[2];
        uint64_t        compat[2];
-       uint8_t         layout[512];
+       struct bcachefs_sb_layout layout;
        struct bcachefs_sb_field _start[];
 }  __attribute__((packed));
 
@@ -144,7 +153,7 @@ struct bcachefs_super_block {
 /* granularity of offset and length fields within superblock */
 #define BCACHEFS_SECTOR_SIZE   512
 /* maximum superblock size */
-#define BCACHEFS_SB_MAX_SIZE   4096
+#define BCACHEFS_SB_MAX_SIZE   0x100000
 /* fields offset within super block */
 #define BCACHEFS_SB_FIELDS_OFF offsetof(struct bcachefs_super_block, _start)
 /* tag value for members field */
@@ -316,6 +325,9 @@ static int probe_bcachefs(blkid_probe pr, const struct blkid_idmag *mag)
                return BLKID_PROBE_NONE;
 
        sb_size = BCACHEFS_SB_FIELDS_OFF + BYTES(bcs);
+       if (sb_size > BCACHEFS_SECTOR_SIZE << bcs->layout.sb_max_size_bits)
+               return BLKID_PROBE_NONE;
+
        if (sb_size > BCACHEFS_SB_MAX_SIZE)
                return BLKID_PROBE_NONE;