Whamcloud - gitweb
e2image: fix metadata image handling on big endian systems
authorLukas Czerner <lczerner@redhat.com>
Mon, 9 Apr 2018 15:58:15 +0000 (11:58 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Mon, 9 Apr 2018 20:20:49 +0000 (16:20 -0400)
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>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
lib/ext2fs/imager.c
lib/ext2fs/inode.c
lib/ext2fs/openfs.c
lib/ext2fs/rw_bitmaps.c
misc/e2image.c

index efb85b9..7fd06f7 100644 (file)
@@ -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;
index ad01a9f..015cfe4 100644 (file)
@@ -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);
index 385d6e8..532e70f 100644 (file)
@@ -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);
        }
 
        /*
index 0b532db..e86bacd 100644 (file)
@@ -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);
index 5a18bb4..83ae633 100644 (file)
@@ -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) {