]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
btrfs: add strict extent map alignment checks
authorQu Wenruo <wqu@suse.com>
Wed, 21 Jan 2026 23:08:00 +0000 (09:38 +1030)
committerDavid Sterba <dsterba@suse.com>
Tue, 3 Feb 2026 06:56:19 +0000 (07:56 +0100)
Currently we do not check the alignment of extent_map structure.

The reasons are the inode and extent-map tests use unaligned values
for start offsets and lengths.

Thankfully those legacy problems are properly addressed by previous
patches, now we can finally put the alignment checks into
validate_extent_map().

Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/extent_map.c

index 7e38c23a0c1cb66d606c709579249ac98b194f2a..095a561d733f0c6f5f5daac01fada717f7b52109 100644 (file)
@@ -319,8 +319,15 @@ static void dump_extent_map(struct btrfs_fs_info *fs_info, const char *prefix,
 /* Internal sanity checks for btrfs debug builds. */
 static void validate_extent_map(struct btrfs_fs_info *fs_info, struct extent_map *em)
 {
+       const u32 blocksize = fs_info->sectorsize;
+
        if (!IS_ENABLED(CONFIG_BTRFS_DEBUG))
                return;
+
+       if (!IS_ALIGNED(em->start, blocksize) ||
+           !IS_ALIGNED(em->len, blocksize))
+               dump_extent_map(fs_info, "unaligned start offset or length members", em);
+
        if (em->disk_bytenr < EXTENT_MAP_LAST_BYTE) {
                if (em->disk_num_bytes == 0)
                        dump_extent_map(fs_info, "zero disk_num_bytes", em);
@@ -334,6 +341,11 @@ static void validate_extent_map(struct btrfs_fs_info *fs_info, struct extent_map
                        dump_extent_map(fs_info,
                "ram_bytes mismatch with disk_num_bytes for non-compressed em",
                                        em);
+               if (!IS_ALIGNED(em->disk_bytenr, blocksize) ||
+                   !IS_ALIGNED(em->disk_num_bytes, blocksize) ||
+                   !IS_ALIGNED(em->offset, blocksize) ||
+                   !IS_ALIGNED(em->ram_bytes, blocksize))
+                       dump_extent_map(fs_info, "unaligned members", em);
        } else if (em->offset) {
                dump_extent_map(fs_info, "non-zero offset for hole/inline", em);
        }