[4/4] ext4: fix rec_len overflow
- prevent rec_len from overflow with 64KB blocksize
Signed-off-by: Takashi Sato <sho@tnes.nec.co.jp>
Signed-off-by: Mingming Cao <cmm@us.ibm.com>
---
fs/ext4/dir.c | 11 ++++--
fs/ext4/namei.c | 88 +++++++++++++++++++++++++++++++++++++++---------
include/linux/ext4_fs.h | 9 ++++
3 files changed, 90 insertions(+), 18 deletions(-)
Index: linux-2.6.23-rc8-mm1/fs/ext4/dir.c
===================================================================
--- linux-2.6.23-rc8-mm1.orig/fs/ext4/dir.c 2007-09-25 14:53:57.000000000 -0700
+++ linux-2.6.23-rc8-mm1/fs/ext4/dir.c 2007-09-25 15:45:09.000000000 -0700
@@ -100,10 +100,11 @@ static int ext4_readdir(struct file * fi
unsigned long offset;
int i, stored;
struct ext4_dir_entry_2 *de;
- struct super_block *sb;
int err;
struct inode *inode = filp->f_path.dentry->d_inode;
+ struct super_block *sb = inode->i_sb;
int ret = 0;
+ unsigned tail = sb->s_blocksize;
sb = inode->i_sb;
@@ -166,8 +167,11 @@ revalidate:
* readdir(2), then we might be pointing to an invalid
* dirent right now. Scan from the start of the block
* to make sure. */
+ if (tail > EXT4_DIR_MAX_REC_LEN)
+ tail = EXT4_DIR_MAX_REC_LEN;
+
if (filp->f_version != inode->i_version) {
- for (i = 0; i < sb->s_blocksize && i < offset; ) {
+ for (i = 0; i < tail && i < offset; ) {
de = (struct ext4_dir_entry_2 *)
(bh->b_data + i);
/* It's too expensive to do a full
@@ -188,7 +192,7 @@ revalidate:
}
while (!error && filp->f_pos < inode->i_size
- && offset < sb->s_blocksize) {
+ && offset < tail) {
de = (struct ext4_dir_entry_2 *) (bh->b_data + offset);
if (!ext4_check_dir_entry ("ext4_readdir", inode, de,
bh, offset)) {
@@ -225,6 +229,7 @@ revalidate:
}
filp->f_pos += le16_to_cpu(de->r...