diff options
author | Theodore Ts'o <tytso@mit.edu> | 2009-01-17 18:41:37 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2009-01-17 18:41:37 -0500 |
commit | 06a279d636734da32bb62dd2f7b0ade666f65d7c (patch) | |
tree | e3fb1a899ea7a9d527ff0d8edf3ca23778321728 /fs | |
parent | c225aa57ff4ffe715df4692676b77c815a337236 (diff) |
ext4: only use i_size_high for regular files
Directories are not allowed to be bigger than 2GB, so don't use
i_size_high for anything other than regular files. E2fsck should
complain about these inodes, but the simplest thing to do for the
kernel is to only use i_size_high for regular files.
This prevents an intentially corrupted filesystem from causing the
kernel to burn a huge amount of CPU and issuing error messages such
as:
EXT4-fs warning (device loop0): ext4_block_to_path: block 135090028 > max
Thanks to David Maciejak from Fortinet's FortiGuard Global Security
Research Team for reporting this issue.
http://bugzilla.kernel.org/show_bug.cgi?id=12375
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Cc: stable@kernel.org
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext4/ext4.h | 7 | ||||
-rw-r--r-- | fs/ext4/inode.c | 4 |
2 files changed, 7 insertions, 4 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index c668e4377d76..aafc9eba1c25 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -1206,8 +1206,11 @@ static inline void ext4_r_blocks_count_set(struct ext4_super_block *es, | |||
1206 | 1206 | ||
1207 | static inline loff_t ext4_isize(struct ext4_inode *raw_inode) | 1207 | static inline loff_t ext4_isize(struct ext4_inode *raw_inode) |
1208 | { | 1208 | { |
1209 | return ((loff_t)le32_to_cpu(raw_inode->i_size_high) << 32) | | 1209 | if (S_ISREG(le16_to_cpu(raw_inode->i_mode))) |
1210 | le32_to_cpu(raw_inode->i_size_lo); | 1210 | return ((loff_t)le32_to_cpu(raw_inode->i_size_high) << 32) | |
1211 | le32_to_cpu(raw_inode->i_size_lo); | ||
1212 | else | ||
1213 | return (loff_t) le32_to_cpu(raw_inode->i_size_lo); | ||
1211 | } | 1214 | } |
1212 | 1215 | ||
1213 | static inline void ext4_isize_set(struct ext4_inode *raw_inode, loff_t i_size) | 1216 | static inline void ext4_isize_set(struct ext4_inode *raw_inode, loff_t i_size) |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index a6444cee0c7e..49484ba801c9 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -360,9 +360,9 @@ static int ext4_block_to_path(struct inode *inode, | |||
360 | final = ptrs; | 360 | final = ptrs; |
361 | } else { | 361 | } else { |
362 | ext4_warning(inode->i_sb, "ext4_block_to_path", | 362 | ext4_warning(inode->i_sb, "ext4_block_to_path", |
363 | "block %lu > max", | 363 | "block %lu > max in inode %lu", |
364 | i_block + direct_blocks + | 364 | i_block + direct_blocks + |
365 | indirect_blocks + double_blocks); | 365 | indirect_blocks + double_blocks, inode->i_ino); |
366 | } | 366 | } |
367 | if (boundary) | 367 | if (boundary) |
368 | *boundary = final - 1 - (i_block & (ptrs - 1)); | 368 | *boundary = final - 1 - (i_block & (ptrs - 1)); |