[patch 2/4] ext2: fix rec_len overflow for 64KB block size

2007-09-25 Thread Christoph Lameter
[2/4]  ext2: fix rec_len overflow
 - prevent rec_len from overflow with 64KB blocksize

Signed-off-by: Takashi Sato [EMAIL PROTECTED]
Signed-off-by: Mingming Cao [EMAIL PROTECTED]
Signed-off-by: Christoph Lameter [EMAIL PROTECTED]

---
 fs/ext2/dir.c   |   46 --
 include/linux/ext2_fs.h |   13 +
 2 files changed, 49 insertions(+), 10 deletions(-)

Index: linux-2.6.23-rc8-mm1/fs/ext2/dir.c
===
--- linux-2.6.23-rc8-mm1.orig/fs/ext2/dir.c 2007-09-25 15:59:34.0 
-0700
+++ linux-2.6.23-rc8-mm1/fs/ext2/dir.c  2007-09-25 16:02:51.0 -0700
@@ -105,9 +105,9 @@ static void ext2_check_page(struct page 
goto out;
}
for (offs = 0; offs = limit - EXT2_DIR_REC_LEN(1); offs += rec_len) {
+   offs = EXT2_DIR_ADJUST_TAIL_OFFS(offs, chunk_size);
p = (ext2_dirent *)(kaddr + offs);
rec_len = le16_to_cpu(p-rec_len);
-
if (rec_len  EXT2_DIR_REC_LEN(1))
goto Eshort;
if (rec_len  3)
@@ -119,6 +119,7 @@ static void ext2_check_page(struct page 
if (le32_to_cpu(p-inode)  max_inumber)
goto Einumber;
}
+   offs = EXT2_DIR_ADJUST_TAIL_OFFS(offs, chunk_size);
if (offs != limit)
goto Eend;
 out:
@@ -294,6 +295,7 @@ ext2_readdir (struct file * filp, void *
de = (ext2_dirent *)(kaddr+offset);
limit = kaddr + ext2_last_byte(inode, n) - EXT2_DIR_REC_LEN(1);
for ( ;(char*)de = limit; de = ext2_next_entry(de)) {
+   de = EXT2_DIR_ADJUST_TAIL_ADDR(kaddr, de, 
sb-s_blocksize);
if (de-rec_len == 0) {
ext2_error(sb, __FUNCTION__,
zero-length directory entry);
@@ -316,8 +318,10 @@ ext2_readdir (struct file * filp, void *
return 0;
}
}
+   filp-f_pos = EXT2_DIR_ADJUST_TAIL_OFFS(filp-f_pos, 
sb-s_blocksize);
filp-f_pos += le16_to_cpu(de-rec_len);
}
+   filp-f_pos = EXT2_DIR_ADJUST_TAIL_OFFS(filp-f_pos, 
sb-s_blocksize);
ext2_put_page(page);
}
return 0;
@@ -354,13 +358,14 @@ struct ext2_dir_entry_2 * ext2_find_entr
start = 0;
n = start;
do {
-   char *kaddr;
+   char *kaddr, *page_start;
page = ext2_get_page(dir, n);
if (!IS_ERR(page)) {
-   kaddr = page_address(page);
+   kaddr = page_start = page_address(page);
de = (ext2_dirent *) kaddr;
kaddr += ext2_last_byte(dir, n) - reclen;
while ((char *) de = kaddr) {
+   de = EXT2_DIR_ADJUST_TAIL_ADDR(page_start, de, 
dir-i_sb-s_blocksize);
if (de-rec_len == 0) {
ext2_error(dir-i_sb, __FUNCTION__,
zero-length directory entry);
@@ -428,6 +433,7 @@ void ext2_set_link(struct inode *dir, st
unsigned len = le16_to_cpu(de-rec_len);
int err;
 
+   len = EXT2_DIR_ADJUST_TAIL_OFFS(pos, len);
lock_page(page);
err = __ext2_write_begin(NULL, page-mapping, pos, len,
AOP_FLAG_UNINTERRUPTIBLE, page, NULL);
@@ -459,6 +465,7 @@ int ext2_add_link (struct dentry *dentry
char *kaddr;
loff_t pos;
int err;
+   char *page_start = NULL;
 
/*
 * We take care of directory expansion in the same loop.
@@ -473,16 +480,29 @@ int ext2_add_link (struct dentry *dentry
if (IS_ERR(page))
goto out;
lock_page(page);
-   kaddr = page_address(page);
+   kaddr = page_start = page_address(page);
dir_end = kaddr + ext2_last_byte(dir, n);
de = (ext2_dirent *)kaddr;
-   kaddr += PAGE_CACHE_SIZE - reclen;
+   if (chunk_size  EXT2_DIR_MAX_REC_LEN)
+   kaddr += PAGE_CACHE_SIZE - reclen;
+   else
+   kaddr += PAGE_CACHE_SIZE -
+   (chunk_size - EXT2_DIR_MAX_REC_LEN) - reclen;
+
while ((char *)de = kaddr) {
+   de = EXT2_DIR_ADJUST_TAIL_ADDR(page_start, de, 
chunk_size);
if ((char *)de == dir_end) {
/* We hit i_size */
name_len = 0;
-   rec_len = chunk_size;
-   de-rec_len = 

Re: [patch 2/4] ext2: fix rec_len overflow for 64KB block size

2007-09-25 Thread Andreas Dilger
On Sep 25, 2007  16:30 -0700, Christoph Lameter wrote:
 [2/4]  ext2: fix rec_len overflow
  - prevent rec_len from overflow with 64KB blocksize
 
 Signed-off-by: Takashi Sato [EMAIL PROTECTED]
 Signed-off-by: Mingming Cao [EMAIL PROTECTED]
 Signed-off-by: Christoph Lameter [EMAIL PROTECTED]

Note that we just got a cleaner implemantation of this code on the ext4
mailing list from Jan Kara yesterday.  Please use that one instead, in
thread Avoid rec_len overflow with 64KB block size instead.

Cheers, Andreas
--
Andreas Dilger
Principal Software Engineer
Cluster File Systems, Inc.

-
To unsubscribe from this list: send the line unsubscribe linux-fsdevel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html