You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

228 lines
7.8 KiB

From 8f575d0b2c297f09491093b9e7ba6b914639be71 Mon Sep 17 00:00:00 2001
From: Lukas Czerner <lczerner@redhat.com>
Date: Mon, 9 Apr 2018 11:58:15 -0400
Subject: [PATCH 4/7] e2image: 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.
RHBZ: 1711880
Signed-off-by: Lukas Czerner <lczerner@redhat.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
---
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 b643cc6f..6caca65b 100644
--- a/lib/ext2fs/imager.c
+++ b/lib/ext2fs/imager.c
@@ -194,6 +194,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)
@@ -203,7 +208,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;
@@ -217,8 +232,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 573a8fa5..4297ec12 100644
--- a/lib/ext2fs/inode.c
+++ b/lib/ext2fs/inode.c
@@ -560,7 +560,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 200f7815..384dbf0f 100644
--- a/lib/ext2fs/openfs.c
+++ b/lib/ext2fs/openfs.c
@@ -177,10 +177,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 ad1d8c80..0e7986b0 100644
--- a/lib/ext2fs/rw_bitmaps.c
+++ b/lib/ext2fs/rw_bitmaps.c
@@ -205,7 +205,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_nbytes > 0) {
retval = io_channel_read_blk64(fs->image_io, blk++,
@@ -223,7 +223,7 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block)
ino_cnt -= fs->blocksize << 3;
inode_nbytes -= fs->blocksize;
}
- 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 98dafa3d..41e54636 100644
--- a/misc/e2image.c
+++ b/misc/e2image.c
@@ -232,7 +232,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",
@@ -240,7 +240,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) {
@@ -249,7 +249,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",
@@ -257,7 +257,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",
@@ -265,23 +265,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);
}
@@ -1406,7 +1406,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.21.1