Skip to content

Commit

Permalink
ext4: Validate extent details only when read from the disk
Browse files Browse the repository at this point in the history
Make sure we validate extent details only when read from the disk.

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Thiemo Nagel <thiemo.nagel@ph.tum.de>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
  • Loading branch information
Aneesh Kumar K.V authored and Theodore Ts'o committed Mar 27, 2009
1 parent 56b1986 commit 7a262f7
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 7 deletions.
1 change: 1 addition & 0 deletions fs/ext4/ext4_extents.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,5 +241,6 @@ extern int ext4_ext_search_left(struct inode *, struct ext4_ext_path *,
extern int ext4_ext_search_right(struct inode *, struct ext4_ext_path *,
ext4_lblk_t *, ext4_fsblk_t *);
extern void ext4_ext_drop_refs(struct ext4_ext_path *);
extern int ext4_ext_check_inode(struct inode *inode);
#endif /* _EXT4_EXTENTS */

25 changes: 18 additions & 7 deletions fs/ext4/extents.c
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,11 @@ static int __ext4_ext_check(const char *function, struct inode *inode,
#define ext4_ext_check(inode, eh, depth) \
__ext4_ext_check(__func__, inode, eh, depth)

int ext4_ext_check_inode(struct inode *inode)
{
return ext4_ext_check(inode, ext_inode_hdr(inode), ext_depth(inode));
}

#ifdef EXT_DEBUG
static void ext4_ext_show_path(struct inode *inode, struct ext4_ext_path *path)
{
Expand Down Expand Up @@ -631,9 +636,6 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,

eh = ext_inode_hdr(inode);
depth = ext_depth(inode);
if (ext4_ext_check(inode, eh, depth))
return ERR_PTR(-EIO);


/* account possible depth increase */
if (!path) {
Expand All @@ -649,6 +651,8 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
i = depth;
/* walk through the tree */
while (i) {
int need_to_validate = 0;

ext_debug("depth %d: num %d, max %d\n",
ppos, le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max));

Expand All @@ -657,18 +661,25 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
path[ppos].p_depth = i;
path[ppos].p_ext = NULL;

bh = sb_bread(inode->i_sb, path[ppos].p_block);
if (!bh)
bh = sb_getblk(inode->i_sb, path[ppos].p_block);
if (unlikely(!bh))
goto err;

if (!bh_uptodate_or_lock(bh)) {
if (bh_submit_read(bh) < 0) {
put_bh(bh);
goto err;
}
/* validate the extent entries */
need_to_validate = 1;
}
eh = ext_block_hdr(bh);
ppos++;
BUG_ON(ppos > depth);
path[ppos].p_bh = bh;
path[ppos].p_hdr = eh;
i--;

if (ext4_ext_check(inode, eh, i))
if (need_to_validate && ext4_ext_check(inode, eh, i))
goto err;
}

Expand Down
10 changes: 10 additions & 0 deletions fs/ext4/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -4345,6 +4345,16 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
(__u64)(le32_to_cpu(raw_inode->i_version_hi)) << 32;
}

if (ei->i_flags & EXT4_EXTENTS_FL) {
/* Validate extent which is part of inode */
ret = ext4_ext_check_inode(inode);
if (ret) {
brelse(bh);
goto bad_inode;
}

}

if (S_ISREG(inode->i_mode)) {
inode->i_op = &ext4_file_inode_operations;
inode->i_fop = &ext4_file_operations;
Expand Down

0 comments on commit 7a262f7

Please sign in to comment.