[U-Boot] [PATCH] fs/ext4: fix calling put_ext4 with truncated offset

Ma Haijun mahaijuns at gmail.com
Wed Jan 8 01:15:33 CET 2014


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 at gmail.com>
---
 fs/ext4/ext4_common.c  | 34 +++++++++++++++++-----------------
 fs/ext4/ext4_journal.c |  8 ++++----
 fs/ext4/ext4_write.c   | 14 +++++++-------
 3 files changed, 28 insertions(+), 28 deletions(-)

diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index 352943e..cff50d8 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -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;
 	}
diff --git a/fs/ext4/ext4_journal.c b/fs/ext4/ext4_journal.c
index d4a46ed..3f61335 100644
--- a/fs/ext4/ext4_journal.c
+++ b/fs/ext4/ext4_journal.c
@@ -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);
diff --git a/fs/ext4/ext4_write.c b/fs/ext4/ext4_write.c
index 1e1924c..b674b6f 100644
--- a/fs/ext4/ext4_write.c
+++ b/fs/ext4/ext4_write.c
@@ -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;
 	}
-- 
1.8.3.2



More information about the U-Boot mailing list