e2fsprogs: fix metadata image handling on big endian systems

Message ID 1522937664-3371-1-git-send-email-lczerner@redhat.com
State Accepted
Headers show
Series
  • e2fsprogs: fix metadata image handling on big endian systems
Related show

Commit Message

Lukas Czerner April 5, 2018, 2:14 p.m.
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 <lczerner@redhat.com>
---
 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(-)

Comments

Theodore Y. Ts'o April 9, 2018, 3:59 p.m. | #1
On Thu, Apr 05, 2018 at 04:14:24PM +0200, Lukas Czerner wrote:
> 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 <lczerner@redhat.com>

Applied, thanks.

					- Ted

Patch

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) {