fs/ext4: fix calling put_ext4 with truncated offset
authorMa Haijun <mahaijuns@gmail.com>
Wed, 8 Jan 2014 00:15:33 +0000 (08:15 +0800)
committerTom Rini <trini@ti.com>
Mon, 20 Jan 2014 15:09:38 +0000 (10:09 -0500)
Curently, we are using 32 bit multiplication to calculate the offset,
so the result will always be 32 bit.
This can silently cause file system corruption when performing a write
operation on partition larger than 4 GiB.

This patch address the issue by simply promoting the terms to 64 bit,
and let compilers decide how to do the multiplication efficiently.

Signed-off-by: Ma Haijun <mahaijuns@gmail.com>
fs/ext4/ext4_common.c
fs/ext4/ext4_journal.c
fs/ext4/ext4_write.c

index 352943ec5145fd873c82cece29d61c601be13906..cff50d8c17ee4204da340c1473c794493c6faa27 100644 (file)
@@ -445,9 +445,9 @@ restart:
                                        goto fail;
                                }
                                put_ext4(((uint64_t)
-                                         (g_parent_inode->b.
+                                         ((uint64_t)g_parent_inode->b.
                                           blocks.dir_blocks[direct_blk_idx] *
-                                          fs->blksz)), zero_buffer, fs->blksz);
+                                          (uint64_t)fs->blksz)), zero_buffer, fs->blksz);
                                g_parent_inode->size =
                                    g_parent_inode->size + fs->blksz;
                                g_parent_inode->blockcnt =
@@ -864,8 +864,8 @@ long int ext4fs_get_new_blk_no(void)
                for (i = 0; i < fs->no_blkgrp; i++) {
                        if (bgd[i].free_blocks) {
                                if (bgd[i].bg_flags & EXT4_BG_BLOCK_UNINIT) {
-                                       put_ext4(((uint64_t) (bgd[i].block_id *
-                                                             fs->blksz)),
+                                       put_ext4(((uint64_t) ((uint64_t)bgd[i].block_id *
+                                                             (uint64_t)fs->blksz)),
                                                 zero_buffer, fs->blksz);
                                        bgd[i].bg_flags =
                                            bgd[i].
@@ -929,8 +929,8 @@ restart:
 
                if (bgd[bg_idx].bg_flags & EXT4_BG_BLOCK_UNINIT) {
                        memset(zero_buffer, '\0', fs->blksz);
-                       put_ext4(((uint64_t) (bgd[bg_idx].block_id *
-                                       fs->blksz)), zero_buffer, fs->blksz);
+                       put_ext4(((uint64_t) ((uint64_t)bgd[bg_idx].block_id *
+                                       (uint64_t)fs->blksz)), zero_buffer, fs->blksz);
                        memcpy(fs->blk_bmaps[bg_idx], zero_buffer, fs->blksz);
                        bgd[bg_idx].bg_flags = bgd[bg_idx].bg_flags &
                                                ~EXT4_BG_BLOCK_UNINIT;
@@ -996,8 +996,8 @@ int ext4fs_get_new_inode_no(void)
                                                bgd[i].free_inodes;
                                if (bgd[i].bg_flags & EXT4_BG_INODE_UNINIT) {
                                        put_ext4(((uint64_t)
-                                                 (bgd[i].inode_id *
-                                                       fs->blksz)),
+                                                 ((uint64_t)bgd[i].inode_id *
+                                                       (uint64_t)fs->blksz)),
                                                 zero_buffer, fs->blksz);
                                        bgd[i].bg_flags = bgd[i].bg_flags &
                                                        ~EXT4_BG_INODE_UNINIT;
@@ -1037,8 +1037,8 @@ restart:
                ibmap_idx = fs->curr_inode_no / inodes_per_grp;
                if (bgd[ibmap_idx].bg_flags & EXT4_BG_INODE_UNINIT) {
                        memset(zero_buffer, '\0', fs->blksz);
-                       put_ext4(((uint64_t) (bgd[ibmap_idx].inode_id *
-                                             fs->blksz)), zero_buffer,
+                       put_ext4(((uint64_t) ((uint64_t)bgd[ibmap_idx].inode_id *
+                                             (uint64_t)fs->blksz)), zero_buffer,
                                 fs->blksz);
                        bgd[ibmap_idx].bg_flags =
                            bgd[ibmap_idx].bg_flags & ~EXT4_BG_INODE_UNINIT;
@@ -1143,7 +1143,7 @@ static void alloc_single_indirect_block(struct ext2_inode *file_inode,
                }
 
                /* write the block to disk */
-               put_ext4(((uint64_t) (si_blockno * fs->blksz)),
+               put_ext4(((uint64_t) ((uint64_t)si_blockno * (uint64_t)fs->blksz)),
                         si_start_addr, fs->blksz);
                file_inode->b.blocks.indir_block = si_blockno;
        }
@@ -1242,7 +1242,7 @@ static void alloc_double_indirect_block(struct ext2_inode *file_inode,
                                        break;
                        }
                        /* write the block  table */
-                       put_ext4(((uint64_t) (di_blockno_child * fs->blksz)),
+                       put_ext4(((uint64_t) ((uint64_t)di_blockno_child * (uint64_t)fs->blksz)),
                                 di_child_buff_start, fs->blksz);
                        free(di_child_buff_start);
                        di_child_buff_start = NULL;
@@ -1250,7 +1250,7 @@ static void alloc_double_indirect_block(struct ext2_inode *file_inode,
                        if (*total_remaining_blocks == 0)
                                break;
                }
-               put_ext4(((uint64_t) (di_blockno_parent * fs->blksz)),
+               put_ext4(((uint64_t) ((uint64_t)di_blockno_parent * (uint64_t)fs->blksz)),
                         di_block_start_addr, fs->blksz);
                file_inode->b.blocks.double_indir_block = di_blockno_parent;
        }
@@ -1348,8 +1348,8 @@ static void alloc_triple_indirect_block(struct ext2_inode *file_inode,
                                                break;
                                }
                                /* write the child block */
-                               put_ext4(((uint64_t) (ti_child_blockno *
-                                                     fs->blksz)),
+                               put_ext4(((uint64_t) ((uint64_t)ti_child_blockno *
+                                                     (uint64_t)fs->blksz)),
                                         ti_cbuff_start_addr, fs->blksz);
                                free(ti_cbuff_start_addr);
 
@@ -1357,7 +1357,7 @@ static void alloc_triple_indirect_block(struct ext2_inode *file_inode,
                                        break;
                        }
                        /* write the parent block */
-                       put_ext4(((uint64_t) (ti_parent_blockno * fs->blksz)),
+                       put_ext4(((uint64_t) ((uint64_t)ti_parent_blockno * (uint64_t)fs->blksz)),
                                 ti_pbuff_start_addr, fs->blksz);
                        free(ti_pbuff_start_addr);
 
@@ -1365,7 +1365,7 @@ static void alloc_triple_indirect_block(struct ext2_inode *file_inode,
                                break;
                }
                /* write the grand parent block */
-               put_ext4(((uint64_t) (ti_gp_blockno * fs->blksz)),
+               put_ext4(((uint64_t) ((uint64_t)ti_gp_blockno * (uint64_t)fs->blksz)),
                         ti_gp_buff_start_addr, fs->blksz);
                file_inode->b.blocks.triple_indir_block = ti_gp_blockno;
        }
index d4a46ed8b65f1565c83a5f3ab20af1b2719f3bc0..3f613351a4328b7a76ed87838dbd965c50038037 100644 (file)
@@ -371,7 +371,7 @@ void recover_transaction(int prev_desc_logical_no)
                blknr = read_allocated_block(&inode_journal, i);
                ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0,
                               fs->blksz, metadata_buff);
-               put_ext4((uint64_t)(be32_to_cpu(tag->block) * fs->blksz),
+               put_ext4((uint64_t)((uint64_t)be32_to_cpu(tag->block) * (uint64_t)fs->blksz),
                         metadata_buff, (uint32_t) fs->blksz);
        } while (!(flags & EXT3_JOURNAL_FLAG_LAST_TAG));
 fail:
@@ -531,7 +531,7 @@ end:
 
                blknr = read_allocated_block(&inode_journal,
                                         EXT2_JOURNAL_SUPERBLOCK);
-               put_ext4((uint64_t) (blknr * fs->blksz),
+               put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
                         (struct journal_superblock_t *)temp_buff,
                         (uint32_t) fs->blksz);
                ext4fs_free_revoke_blks();
@@ -590,7 +590,7 @@ static void update_descriptor_block(long int blknr)
        tag.flags = cpu_to_be32(EXT3_JOURNAL_FLAG_LAST_TAG);
        memcpy(temp - sizeof(struct ext3_journal_block_tag), &tag,
               sizeof(struct ext3_journal_block_tag));
-       put_ext4((uint64_t) (blknr * fs->blksz), buf, (uint32_t) fs->blksz);
+       put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz);
 
        free(temp_buff);
        free(buf);
@@ -625,7 +625,7 @@ static void update_commit_block(long int blknr)
                return;
        }
        memcpy(buf, &jdb, sizeof(struct journal_header_t));
-       put_ext4((uint64_t) (blknr * fs->blksz), buf, (uint32_t) fs->blksz);
+       put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz), buf, (uint32_t) fs->blksz);
 
        free(temp_buff);
        free(buf);
index 1e1924c80626f4835f61e7f6dc9aa6f9b4682a7e..b674b6faebe2d214e58909d4f90dc2857972b1ab 100644 (file)
@@ -40,18 +40,18 @@ static void ext4fs_update(void)
        /* update block groups */
        for (i = 0; i < fs->no_blkgrp; i++) {
                fs->bgd[i].bg_checksum = ext4fs_checksum_update(i);
-               put_ext4((uint64_t)(fs->bgd[i].block_id * fs->blksz),
+               put_ext4((uint64_t)((uint64_t)fs->bgd[i].block_id * (uint64_t)fs->blksz),
                         fs->blk_bmaps[i], fs->blksz);
        }
 
        /* update inode table groups */
        for (i = 0; i < fs->no_blkgrp; i++) {
-               put_ext4((uint64_t) (fs->bgd[i].inode_id * fs->blksz),
+               put_ext4((uint64_t) ((uint64_t)fs->bgd[i].inode_id * (uint64_t)fs->blksz),
                         fs->inode_bmaps[i], fs->blksz);
        }
 
        /* update the block group descriptor table */
-       put_ext4((uint64_t)(fs->gdtable_blkno * fs->blksz),
+       put_ext4((uint64_t)((uint64_t)fs->gdtable_blkno * (uint64_t)fs->blksz),
                 (struct ext2_block_group *)fs->gdtable,
                 (fs->blksz * fs->no_blk_pergdt));
 
@@ -709,7 +709,7 @@ void ext4fs_deinit(void)
                               temp_buff);
                jsb = (struct journal_superblock_t *)temp_buff;
                jsb->s_start = cpu_to_be32(0);
-               put_ext4((uint64_t) (blknr * fs->blksz),
+               put_ext4((uint64_t) ((uint64_t)blknr * (uint64_t)fs->blksz),
                         (struct journal_superblock_t *)temp_buff, fs->blksz);
                free(temp_buff);
        }
@@ -793,7 +793,7 @@ static int ext4fs_write_file(struct ext2_inode *file_inode,
                                        delayed_next += blockend >> log2blksz;
                                } else {        /* spill */
                                        put_ext4((uint64_t)
-                                                (delayed_start << log2blksz),
+                                                ((uint64_t)delayed_start << log2blksz),
                                                 delayed_buf,
                                                 (uint32_t) delayed_extent);
                                        previous_block_number = blknr;
@@ -814,7 +814,7 @@ static int ext4fs_write_file(struct ext2_inode *file_inode,
                } else {
                        if (previous_block_number != -1) {
                                /* spill */
-                               put_ext4((uint64_t) (delayed_start <<
+                               put_ext4((uint64_t) ((uint64_t)delayed_start <<
                                                     log2blksz),
                                         delayed_buf,
                                         (uint32_t) delayed_extent);
@@ -826,7 +826,7 @@ static int ext4fs_write_file(struct ext2_inode *file_inode,
        }
        if (previous_block_number != -1) {
                /* spill */
-               put_ext4((uint64_t) (delayed_start << log2blksz),
+               put_ext4((uint64_t) ((uint64_t)delayed_start << log2blksz),
                         delayed_buf, (uint32_t) delayed_extent);
                previous_block_number = -1;
        }