diff options
Diffstat (limited to 'fs/squashfs/namei.c')
| -rw-r--r-- | fs/squashfs/namei.c | 40 |
1 files changed, 25 insertions, 15 deletions
diff --git a/fs/squashfs/namei.c b/fs/squashfs/namei.c index 9e398653b22..67cad77fefb 100644 --- a/fs/squashfs/namei.c +++ b/fs/squashfs/namei.c @@ -2,7 +2,7 @@ * Squashfs - a compressed read only filesystem for Linux * * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 - * Phillip Lougher <phillip@lougher.demon.co.uk> + * Phillip Lougher <phillip@squashfs.org.uk> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -57,12 +57,13 @@ #include <linux/slab.h> #include <linux/string.h> #include <linux/dcache.h> -#include <linux/zlib.h> +#include <linux/xattr.h> #include "squashfs_fs.h" #include "squashfs_fs_sb.h" #include "squashfs_fs_i.h" #include "squashfs.h" +#include "xattr.h" /* * Lookup name in the directory index, returning the location of the metadata @@ -78,7 +79,8 @@ static int get_dir_index_using_name(struct super_block *sb, int len) { struct squashfs_sb_info *msblk = sb->s_fs_info; - int i, size, length = 0, err; + int i, length = 0, err; + unsigned int size; struct squashfs_dir_index *index; char *str; @@ -102,6 +104,8 @@ static int get_dir_index_using_name(struct super_block *sb, size = le32_to_cpu(index->size) + 1; + if (size > SQUASHFS_NAME_LEN) + break; err = squashfs_read_metadata(sb, index->name, &index_start, &index_offset, size); @@ -133,7 +137,7 @@ out: static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry, - struct nameidata *nd) + unsigned int flags) { const unsigned char *name = dentry->d_name.name; int len = dentry->d_name.len; @@ -143,7 +147,8 @@ static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry, struct squashfs_dir_entry *dire; u64 block = squashfs_i(dir)->start + msblk->directory_table; int offset = squashfs_i(dir)->offset; - int err, length = 0, dir_count, size; + int err, length; + unsigned int dir_count, size; TRACE("Entered squashfs_lookup [%llx:%x]\n", block, offset); @@ -175,6 +180,10 @@ static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry, length += sizeof(dirh); dir_count = le32_to_cpu(dirh.count) + 1; + + if (dir_count > SQUASHFS_DIR_COUNT) + goto data_error; + while (dir_count--) { /* * Read directory entry. @@ -186,6 +195,10 @@ static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry, size = le16_to_cpu(dire->size) + 1; + /* size should never be larger than SQUASHFS_NAME_LEN */ + if (size > SQUASHFS_NAME_LEN) + goto data_error; + err = squashfs_read_metadata(dir->i_sb, dire->name, &block, &offset, size); if (err < 0) @@ -210,11 +223,6 @@ static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry, blk, off, ino_num); inode = squashfs_iget(dir->i_sb, ino, ino_num); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - goto failed; - } - goto exit_lookup; } } @@ -222,10 +230,10 @@ static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry, exit_lookup: kfree(dire); - if (inode) - return d_splice_alias(inode, dentry); - d_add(dentry, inode); - return ERR_PTR(0); + return d_splice_alias(inode, dentry); + +data_error: + err = -EIO; read_failure: ERROR("Unable to read directory block [%llx:%x]\n", @@ -238,5 +246,7 @@ failed: const struct inode_operations squashfs_dir_inode_ops = { - .lookup = squashfs_lookup + .lookup = squashfs_lookup, + .getxattr = generic_getxattr, + .listxattr = squashfs_listxattr }; |
