From cb41ca55157dda921075f681986c6bf1b825a13b Mon Sep 17 00:00:00 2001 From: Lukas Czerner Date: Tue, 10 Apr 2018 13:00:54 +0200 Subject: [PATCH] e2fsprogs: fix metadata image handling on big endian systems Currently e2image metadata image handling and creating is completely broken on big endian systems. It just does not care about endianness at all. This was uncovered With addition of i_bitmaps test, which is the first test that actually tests e2image metadata image. Fix it by making sure that all on-disk metadata that we write and read to/from the metadata image is properly converted. Signed-off-by: Lukas Czerner --- ...tadata-image-handling-on-big-endian-.patch | 225 ++++++++++++++++++ e2fsprogs.spec | 4 + 2 files changed, 229 insertions(+) create mode 100644 0001-e2fsprogs-fix-metadata-image-handling-on-big-endian-.patch diff --git a/0001-e2fsprogs-fix-metadata-image-handling-on-big-endian-.patch b/0001-e2fsprogs-fix-metadata-image-handling-on-big-endian-.patch new file mode 100644 index 0000000..d576a1b --- /dev/null +++ b/0001-e2fsprogs-fix-metadata-image-handling-on-big-endian-.patch @@ -0,0 +1,225 @@ +From eb8758e89150306a0c699ab7ad3d774ca38d0363 Mon Sep 17 00:00:00 2001 +From: Lukas Czerner +Date: Thu, 5 Apr 2018 16:02:28 +0200 +Subject: [PATCH] e2fsprogs: fix metadata image handling on big endian systems + +Currently e2image metadata image handling and creating is completely +broken on big endian systems. It just does not care about endianness at +all. This was uncovered With addition of i_bitmaps test, which is the +first test that actually tests e2image metadata image. + +Fix it by making sure that all on-disk metadata that we write and read +to/from the metadata image is properly converted. + +Signed-off-by: Lukas Czerner +--- + lib/ext2fs/imager.c | 41 +++++++++++++++++++++++++++++++++++++++++ + lib/ext2fs/inode.c | 2 +- + lib/ext2fs/openfs.c | 4 ++-- + lib/ext2fs/rw_bitmaps.c | 4 ++-- + misc/e2image.c | 22 +++++++++++----------- + 5 files changed, 57 insertions(+), 16 deletions(-) + +diff --git a/lib/ext2fs/imager.c b/lib/ext2fs/imager.c +index efb85b9..7fd06f7 100644 +--- a/lib/ext2fs/imager.c ++++ b/lib/ext2fs/imager.c +@@ -195,6 +195,11 @@ errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd, + char *buf, *cp; + ssize_t actual; + errcode_t retval; ++#ifdef WORDS_BIGENDIAN ++ unsigned int groups_per_block; ++ struct ext2_group_desc *gdp; ++ int j; ++#endif + + buf = malloc(fs->blocksize); + if (!buf) +@@ -204,7 +209,17 @@ errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd, + * Write out the superblock + */ + memset(buf, 0, fs->blocksize); ++#ifdef WORDS_BIGENDIAN ++ /* ++ * We're writing out superblock so let's convert ++ * it to little endian and then back if needed ++ */ ++ ext2fs_swap_super(fs->super); + memcpy(buf, fs->super, SUPERBLOCK_SIZE); ++ ext2fs_swap_super(fs->super); ++#else ++ memcpy(buf, fs->super, SUPERBLOCK_SIZE); ++#endif + actual = write(fd, buf, fs->blocksize); + if (actual == -1) { + retval = errno; +@@ -218,8 +233,34 @@ errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd, + /* + * Now write out the block group descriptors + */ ++ + cp = (char *) fs->group_desc; ++ ++#ifdef WORDS_BIGENDIAN ++ /* ++ * Convert group descriptors to little endian and back ++ * if needed ++ */ ++ groups_per_block = EXT2_DESC_PER_BLOCK(fs->super); ++ gdp = (struct ext2_group_desc *) cp; ++ for (j=0; j < groups_per_block*fs->desc_blocks; j++) { ++ gdp = ext2fs_group_desc(fs, fs->group_desc, j); ++ ext2fs_swap_group_desc2(fs, gdp); ++ } ++#endif ++ + actual = write(fd, cp, fs->blocksize * fs->desc_blocks); ++ ++ ++#ifdef WORDS_BIGENDIAN ++ groups_per_block = EXT2_DESC_PER_BLOCK(fs->super); ++ gdp = (struct ext2_group_desc *) cp; ++ for (j=0; j < groups_per_block*fs->desc_blocks; j++) { ++ gdp = ext2fs_group_desc(fs, fs->group_desc, j); ++ ext2fs_swap_group_desc2(fs, gdp); ++ } ++#endif ++ + if (actual == -1) { + retval = errno; + goto errout; +diff --git a/lib/ext2fs/inode.c b/lib/ext2fs/inode.c +index ad01a9f..015cfe4 100644 +--- a/lib/ext2fs/inode.c ++++ b/lib/ext2fs/inode.c +@@ -770,7 +770,7 @@ errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino, + } + if (fs->flags & EXT2_FLAG_IMAGE_FILE) { + inodes_per_block = fs->blocksize / EXT2_INODE_SIZE(fs->super); +- block_nr = fs->image_header->offset_inode / fs->blocksize; ++ block_nr = ext2fs_le32_to_cpu(fs->image_header->offset_inode) / fs->blocksize; + block_nr += (ino - 1) / inodes_per_block; + offset = ((ino - 1) % inodes_per_block) * + EXT2_INODE_SIZE(fs->super); +diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c +index 385d6e8..532e70f 100644 +--- a/lib/ext2fs/openfs.c ++++ b/lib/ext2fs/openfs.c +@@ -185,10 +185,10 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, + fs->image_header); + if (retval) + goto cleanup; +- if (fs->image_header->magic_number != EXT2_ET_MAGIC_E2IMAGE) ++ if (ext2fs_le32_to_cpu(fs->image_header->magic_number) != EXT2_ET_MAGIC_E2IMAGE) + return EXT2_ET_MAGIC_E2IMAGE; + superblock = 1; +- block_size = fs->image_header->fs_blocksize; ++ block_size = ext2fs_le32_to_cpu(fs->image_header->fs_blocksize); + } + + /* +diff --git a/lib/ext2fs/rw_bitmaps.c b/lib/ext2fs/rw_bitmaps.c +index 0b532db..e86bacd 100644 +--- a/lib/ext2fs/rw_bitmaps.c ++++ b/lib/ext2fs/rw_bitmaps.c +@@ -253,7 +253,7 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) + ext2fs_free_mem(&buf); + + if (fs->flags & EXT2_FLAG_IMAGE_FILE) { +- blk = (fs->image_header->offset_inodemap / fs->blocksize); ++ blk = (ext2fs_le32_to_cpu(fs->image_header->offset_inodemap) / fs->blocksize); + ino_cnt = fs->super->s_inodes_count; + while (inode_bitmap && ino_cnt > 0) { + retval = io_channel_read_blk64(fs->image_io, blk++, +@@ -270,7 +270,7 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) + ino_itr += cnt; + ino_cnt -= cnt; + } +- blk = (fs->image_header->offset_blockmap / ++ blk = (ext2fs_le32_to_cpu(fs->image_header->offset_blockmap) / + fs->blocksize); + blk_cnt = EXT2_GROUPS_TO_CLUSTERS(fs->super, + fs->group_desc_count); +diff --git a/misc/e2image.c b/misc/e2image.c +index 5a18bb4..83ae633 100644 +--- a/misc/e2image.c ++++ b/misc/e2image.c +@@ -240,7 +240,7 @@ static void write_image_file(ext2_filsys fs, int fd) + write_header(fd, NULL, sizeof(struct ext2_image_hdr), fs->blocksize); + memset(&hdr, 0, sizeof(struct ext2_image_hdr)); + +- hdr.offset_super = seek_relative(fd, 0); ++ hdr.offset_super = ext2fs_cpu_to_le32(seek_relative(fd, 0)); + retval = ext2fs_image_super_write(fs, fd, 0); + if (retval) { + com_err(program_name, retval, "%s", +@@ -248,7 +248,7 @@ static void write_image_file(ext2_filsys fs, int fd) + exit(1); + } + +- hdr.offset_inode = seek_relative(fd, 0); ++ hdr.offset_inode = ext2fs_cpu_to_le32(seek_relative(fd, 0)); + retval = ext2fs_image_inode_write(fs, fd, + (fd != 1) ? IMAGER_FLAG_SPARSEWRITE : 0); + if (retval) { +@@ -257,7 +257,7 @@ static void write_image_file(ext2_filsys fs, int fd) + exit(1); + } + +- hdr.offset_blockmap = seek_relative(fd, 0); ++ hdr.offset_blockmap = ext2fs_cpu_to_le32(seek_relative(fd, 0)); + retval = ext2fs_image_bitmap_write(fs, fd, 0); + if (retval) { + com_err(program_name, retval, "%s", +@@ -265,7 +265,7 @@ static void write_image_file(ext2_filsys fs, int fd) + exit(1); + } + +- hdr.offset_inodemap = seek_relative(fd, 0); ++ hdr.offset_inodemap = ext2fs_cpu_to_le32(seek_relative(fd, 0)); + retval = ext2fs_image_bitmap_write(fs, fd, IMAGER_FLAG_INODEMAP); + if (retval) { + com_err(program_name, retval, "%s", +@@ -273,23 +273,23 @@ static void write_image_file(ext2_filsys fs, int fd) + exit(1); + } + +- hdr.magic_number = EXT2_ET_MAGIC_E2IMAGE; ++ hdr.magic_number = ext2fs_cpu_to_le32(EXT2_ET_MAGIC_E2IMAGE); + strcpy(hdr.magic_descriptor, "Ext2 Image 1.0"); + gethostname(hdr.fs_hostname, sizeof(hdr.fs_hostname)); + strncpy(hdr.fs_device_name, device_name, sizeof(hdr.fs_device_name)-1); + hdr.fs_device_name[sizeof(hdr.fs_device_name) - 1] = 0; +- hdr.fs_blocksize = fs->blocksize; ++ hdr.fs_blocksize = ext2fs_cpu_to_le32(fs->blocksize); + + if (stat(device_name, &st) == 0) +- hdr.fs_device = st.st_rdev; ++ hdr.fs_device = ext2fs_cpu_to_le32(st.st_rdev); + + if (fstat(fd, &st) == 0) { +- hdr.image_device = st.st_dev; +- hdr.image_inode = st.st_ino; ++ hdr.image_device = ext2fs_cpu_to_le32(st.st_dev); ++ hdr.image_inode = ext2fs_cpu_to_le32(st.st_ino); + } + memcpy(hdr.fs_uuid, fs->super->s_uuid, sizeof(hdr.fs_uuid)); + +- hdr.image_time = time(0); ++ hdr.image_time = ext2fs_cpu_to_le32(time(0)); + write_header(fd, &hdr, sizeof(struct ext2_image_hdr), fs->blocksize); + } + +@@ -1423,7 +1423,7 @@ static void install_image(char *device, char *image_fn, int type) + + ext2fs_rewrite_to_io(fs, io); + +- seek_set(fd, fs->image_header->offset_inode); ++ seek_set(fd, ext2fs_le32_to_cpu(fs->image_header->offset_inode)); + + retval = ext2fs_image_inode_read(fs, fd, 0); + if (retval) { +-- +2.7.5 + diff --git a/e2fsprogs.spec b/e2fsprogs.spec index f212120..15652f1 100644 --- a/e2fsprogs.spec +++ b/e2fsprogs.spec @@ -11,6 +11,7 @@ Source1: ext2_types-wrapper.h Source2: e2fsck.conf Patch1: e2fsprogs-1.44.1-tests_use_mke2fs_and_debugfs_from_the_build_tree.patch +Patch2: 0001-e2fsprogs-fix-metadata-image-handling-on-big-endian-.patch Url: http://e2fsprogs.sourceforge.net/ Requires: e2fsprogs-libs%{?_isa} = %{version}-%{release} @@ -148,6 +149,8 @@ It was originally inspired by the Multics SubSystem library. %setup -q # tests: use mke2fs and debugfs from the build tree %patch1 -p1 +# e2fsprogs: fix metadata image handling on big endian systems +%patch2 -p1 %build @@ -331,6 +334,7 @@ exit 0 - New upstream release - tests: use mke2fs and debugfs from the build tree - remove custom patch to ignose sb feature differences +- e2fsprogs: fix metadata image handling on big endian systems * Mon Mar 12 2018 Lukas Czerner 1.44.0-2 - e2fsck: fix endianness problem when reading htree nodes