From: Mingming Cao <cmm@us.ibm.com>
To: clameter@sgi.com, linux-fsdevel@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, adilger@clusterfs.com,
sho@tnes.nec.co.jp, ext4 development <linux-ext4@vger.kernel.org>
Subject: [RFC 2/4]ext2: fix rec_len overflow with 64KB block size
Date: Wed, 29 Aug 2007 17:47:53 -0700 [thread overview]
Message-ID: <1188434873.3799.78.camel@localhost.localdomain> (raw)
In-Reply-To: <1188432669.3799.35.camel@localhost.localdomain>
[2/4] ext2: 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/ext2/dir.c | 46 ++++++++++++++++++++++++++++++++++++----------
include/linux/ext2_fs.h | 13 +++++++++++++
2 files changed, 49 insertions(+), 10 deletions(-)
Index: linux-2.6.23-rc3/fs/ext2/dir.c
===================================================================
--- linux-2.6.23-rc3.orig/fs/ext2/dir.c 2007-08-12 21:25:24.000000000 -0700
+++ linux-2.6.23-rc3/fs/ext2/dir.c 2007-08-29 15:29:51.000000000 -0700
@@ -94,9 +94,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)
@@ -108,6 +108,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:
@@ -283,6 +284,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");
@@ -305,8 +307,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;
@@ -343,13 +347,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");
@@ -416,6 +421,7 @@ void ext2_set_link(struct inode *dir, st
unsigned to = from + le16_to_cpu(de->rec_len);
int err;
+ to = EXT2_DIR_ADJUST_TAIL_OFFS(to, inode->i_sb->s_blocksize);
lock_page(page);
err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
BUG_ON(err);
@@ -446,6 +452,7 @@ int ext2_add_link (struct dentry *dentry
char *kaddr;
unsigned from, to;
int err;
+ char *page_start = NULL;
/*
* We take care of directory expansion in the same loop.
@@ -460,16 +467,28 @@ 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 = cpu_to_le16(chunk_size);
+ if (chunk_size < EXT2_DIR_MAX_REC_LEN) {
+ rec_len = chunk_size;
+ de->rec_len = cpu_to_le16(chunk_size);
+ } else {
+ rec_len = EXT2_DIR_MAX_REC_LEN;
+ de->rec_len =
+ cpu_to_le16(EXT2_DIR_MAX_REC_LEN);
+ }
de->inode = 0;
goto got_it;
}
@@ -499,6 +518,7 @@ int ext2_add_link (struct dentry *dentry
got_it:
from = (char*)de - (char*)page_address(page);
to = from + rec_len;
+ to = EXT2_DIR_ADJUST_TAIL_OFFS(to, chunk_size);
err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
if (err)
goto out_unlock;
@@ -541,6 +561,7 @@ int ext2_delete_entry (struct ext2_dir_e
ext2_dirent * de = (ext2_dirent *) (kaddr + from);
int err;
+ to = EXT2_DIR_ADJUST_TAIL_OFFS(to, inode->i_sb->s_blocksize);
while ((char*)de < (char*)dir) {
if (de->rec_len == 0) {
ext2_error(inode->i_sb, __FUNCTION__,
@@ -598,7 +619,11 @@ int ext2_make_empty(struct inode *inode,
de = (struct ext2_dir_entry_2 *)(kaddr + EXT2_DIR_REC_LEN(1));
de->name_len = 2;
- de->rec_len = cpu_to_le16(chunk_size - EXT2_DIR_REC_LEN(1));
+ if (chunk_size < EXT2_DIR_MAX_REC_LEN) {
+ de->rec_len = cpu_to_le16(chunk_size - EXT2_DIR_REC_LEN(1));
+ } else {
+ de->rec_len = cpu_to_le16(EXT2_DIR_MAX_REC_LEN - EXT2_DIR_REC_LEN(1));
+ }
de->inode = cpu_to_le32(parent->i_ino);
memcpy (de->name, "..\0", 4);
ext2_set_de_type (de, inode);
@@ -618,18 +643,19 @@ int ext2_empty_dir (struct inode * inode
unsigned long i, npages = dir_pages(inode);
for (i = 0; i < npages; i++) {
- char *kaddr;
+ char *kaddr, *page_start;
ext2_dirent * de;
page = ext2_get_page(inode, i);
if (IS_ERR(page))
continue;
- kaddr = page_address(page);
+ kaddr = page_start = page_address(page);
de = (ext2_dirent *)kaddr;
kaddr += ext2_last_byte(inode, i) - EXT2_DIR_REC_LEN(1);
while ((char *)de <= kaddr) {
+ de = EXT2_DIR_ADJUST_TAIL_ADDR(page_start, de, inode->i_sb->s_blocksize);
if (de->rec_len == 0) {
ext2_error(inode->i_sb, __FUNCTION__,
"zero-length directory entry");
Index: linux-2.6.23-rc3/include/linux/ext2_fs.h
===================================================================
--- linux-2.6.23-rc3.orig/include/linux/ext2_fs.h 2007-08-29 15:22:29.000000000 -0700
+++ linux-2.6.23-rc3/include/linux/ext2_fs.h 2007-08-29 15:29:51.000000000 -0700
@@ -557,5 +557,18 @@ enum {
#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)
#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
~EXT2_DIR_ROUND)
+#define EXT2_DIR_MAX_REC_LEN 65532
+
+/*
+ * Align a tail offset(address) to the end of a directory block
+ */
+#define EXT2_DIR_ADJUST_TAIL_OFFS(offs, bsize) \
+ ((((offs) & ((bsize) -1)) == EXT2_DIR_MAX_REC_LEN) ? \
+ ((offs) + (bsize) - EXT2_DIR_MAX_REC_LEN):(offs))
+
+#define EXT2_DIR_ADJUST_TAIL_ADDR(page, de, bsize) \
+ (((((char*)(de) - (page)) & ((bsize) - 1)) == EXT2_DIR_MAX_REC_LEN) ? \
+ ((ext2_dirent*)((char*)(de) + (bsize) - EXT2_DIR_MAX_REC_LEN)):(de))
#endif /* _LINUX_EXT2_FS_H */
+
next prev parent reply other threads:[~2007-08-30 0:47 UTC|newest]
Thread overview: 56+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20070828190551.415127746@sgi.com>
[not found] ` <20070828190735.292638294@sgi.com>
2007-08-30 0:11 ` [31/36] Large Blocksize: Core piece Mingming Cao
2007-08-30 0:12 ` Christoph Lameter
2007-08-30 0:47 ` [RFC 1/4] Large Blocksize support for Ext2/3/4 Mingming Cao
2007-08-30 0:59 ` Christoph Lameter
2007-09-01 0:01 ` Mingming Cao
2007-09-01 0:12 ` [RFC 1/2] JBD: slab management support for large block(>8k) Mingming Cao
2007-09-01 18:39 ` Christoph Hellwig
2007-09-02 11:40 ` Christoph Lameter
2007-09-02 15:28 ` Christoph Hellwig
2007-09-03 7:55 ` Christoph Lameter
2007-09-03 13:40 ` Christoph Hellwig
2007-09-03 19:31 ` Christoph Lameter
2007-09-03 19:33 ` Christoph Hellwig
2007-09-14 18:53 ` [PATCH] JBD slab cleanups Mingming Cao
2007-09-14 18:58 ` Christoph Lameter
2007-09-17 19:29 ` Mingming Cao
2007-09-17 19:34 ` Christoph Hellwig
2007-09-17 22:01 ` Badari Pulavarty
2007-09-17 22:57 ` Mingming Cao
2007-09-18 9:04 ` Christoph Hellwig
2007-09-18 16:35 ` Mingming Cao
2007-09-18 18:04 ` Dave Kleikamp
2007-09-19 1:00 ` Mingming Cao
2007-09-19 2:19 ` Andrew Morton
2007-09-19 19:15 ` Mingming Cao
2007-09-19 19:22 ` [PATCH] JBD: use GFP_NOFS in kmalloc Mingming Cao
2007-09-19 21:34 ` Andrew Morton
2007-09-19 21:55 ` Mingming Cao
2007-09-20 4:25 ` Andreas Dilger
2007-09-19 19:26 ` [PATCH] JBD slab cleanups Dave Kleikamp
2007-09-19 19:28 ` Dave Kleikamp
2007-09-19 20:47 ` Mingming Cao
2007-09-19 19:48 ` Andreas Dilger
2007-09-19 22:03 ` Mingming Cao
2007-09-01 0:12 ` [RFC 2/2] JBD: blocks reservation fix for large block support Mingming Cao
2007-08-30 0:47 ` Mingming Cao [this message]
[not found] ` <20070828190730.220393749@sgi.com>
2007-08-30 9:20 ` [11/36] Use page_cache_xxx in fs/buffer.c Dmitry Monakhov
2007-08-30 18:14 ` Christoph Lameter
2007-08-31 1:47 ` Christoph Lameter
2007-08-31 6:56 ` Jens Axboe
2007-08-31 7:03 ` Christoph Lameter
2007-08-31 7:11 ` Jens Axboe
2007-08-31 7:17 ` Christoph Lameter
2007-08-31 7:26 ` Jens Axboe
2007-08-31 7:33 ` Christoph Lameter
2007-08-31 7:43 ` Jens Axboe
2007-08-31 7:52 ` Christoph Lameter
2007-08-31 8:12 ` Jens Axboe
2007-08-31 15:22 ` Christoph Lameter
2007-08-31 16:35 ` Jörn Engel
2007-08-31 19:00 ` Jens Axboe
2007-08-31 8:36 ` Dmitry Monakhov
2007-08-31 15:28 ` Christoph Lameter
[not found] ` <20070828192034.GA13883@lst.de>
[not found] ` <Pine.LNX.4.64.0708281254070.16473@schroedinger.engr.sgi.com>
2007-09-01 1:11 ` [00/36] Large Blocksize Support V6 Christoph Lameter
2007-09-01 19:17 ` Peter Zijlstra
2007-09-02 11:44 ` Christoph Lameter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1188434873.3799.78.camel@localhost.localdomain \
--to=cmm@us.ibm.com \
--cc=adilger@clusterfs.com \
--cc=clameter@sgi.com \
--cc=linux-ext4@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=sho@tnes.nec.co.jp \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).