]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
libext2fs: fix problems with LE<->BE conversions on BE platforms
authorDarrick J. Wong <darrick.wong@oracle.com>
Mon, 25 Aug 2014 02:01:36 +0000 (22:01 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Mon, 25 Aug 2014 02:01:36 +0000 (22:01 -0400)
Fix more problems that I found when testing on ppc64:

- Inode swap cut and paste error leads to immutable inodes being
  detected as inlinedata inodes, leading to e2fsck incorrectly barfing
  on i_block[] contents.

- Superblock csum/verify must be aware of the fs->super byte order
  when checking for metadata_csum feature flag.  (Hint: in _openfs(),
  fs->super is in LE order for the first csum verification)

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
lib/ext2fs/csum.c
lib/ext2fs/swapfs.c

index d7dbca83339430912bbf5b71e217accb3d6e8814..12f6fe9fc117603d7df20cd6f0fdcb8febb1c5ae 100644 (file)
@@ -81,12 +81,17 @@ static __u32 ext2fs_superblock_csum(ext2_filsys fs EXT2FS_ATTR((unused)),
        return ext2fs_crc32c_le(~0, (unsigned char *)sb, offset);
 }
 
+/* NOTE: The input to this function MUST be in LE order */
 int ext2fs_superblock_csum_verify(ext2_filsys fs, struct ext2_super_block *sb)
 {
-       __u32 calculated;
+       __u32 flag, calculated;
 
-       if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-                                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (fs->flags & EXT2_FLAG_SWAP_BYTES)
+               flag = EXT4_FEATURE_RO_COMPAT_METADATA_CSUM;
+       else
+               flag = ext2fs_cpu_to_le32(EXT4_FEATURE_RO_COMPAT_METADATA_CSUM);
+
+       if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, flag))
                return 1;
 
        calculated = ext2fs_superblock_csum(fs, sb);
@@ -94,13 +99,18 @@ int ext2fs_superblock_csum_verify(ext2_filsys fs, struct ext2_super_block *sb)
        return ext2fs_le32_to_cpu(sb->s_checksum) == calculated;
 }
 
+/* NOTE: The input to this function MUST be in LE order */
 errcode_t ext2fs_superblock_csum_set(ext2_filsys fs,
                                     struct ext2_super_block *sb)
 {
-       __u32 crc;
+       __u32 flag, crc;
 
-       if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-               EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+       if (fs->flags & EXT2_FLAG_SWAP_BYTES)
+               flag = EXT4_FEATURE_RO_COMPAT_METADATA_CSUM;
+       else
+               flag = ext2fs_cpu_to_le32(EXT4_FEATURE_RO_COMPAT_METADATA_CSUM);
+
+       if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, flag))
                return 0;
 
        crc = ext2fs_superblock_csum(fs, sb);
@@ -756,8 +766,8 @@ __u16 ext2fs_group_desc_csum(ext2_filsys fs, dgrp_t group)
 #ifdef WORDS_BIGENDIAN
                if (save_size > ext4_bg_size)
                        crc32 = ext2fs_crc32c_le(crc32,
-                                          (char *)save_desc + ext4_bg_size,
-                                          save_size - ext4_bg_size);
+                                    (unsigned char *)save_desc + ext4_bg_size,
+                                    save_size - ext4_bg_size);
 #endif
                crc = crc32 & 0xFFFF;
                goto out;
index e2aa41dcaf6215aa15361eccd989ccb45271b305..ee7a4559159899c07681975b9599775880f2cea8 100644 (file)
@@ -243,7 +243,7 @@ void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t,
        t->i_flags = ext2fs_swab32(f->i_flags);
        if (!hostorder && (t->i_flags & EXT4_EXTENTS_FL))
                has_extents = 1;
-       if (!hostorder && (f->i_flags & EXT4_INLINE_DATA_FL))
+       if (!hostorder && (t->i_flags & EXT4_INLINE_DATA_FL))
                has_inline_data = 1;
        t->i_dir_acl = ext2fs_swab32(f->i_dir_acl);
        /*