summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-05-26 17:27:35 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2011-05-26 17:27:35 -0700
commitbc9bc72e2f9bb07384c00604d1a40d0b5f62be6c (patch)
tree99fc71a5d5889445fb39279d7ff3f0d66c1cca0d
parent968d803c98410910fbadca031b6a873d4bc12dd5 (diff)
parentd7f2ff6718efa155fd92e481a5960496d084c63f (diff)
downloadlinux-stable-bc9bc72e2f9bb07384c00604d1a40d0b5f62be6c.tar.gz
linux-stable-bc9bc72e2f9bb07384c00604d1a40d0b5f62be6c.tar.bz2
linux-stable-bc9bc72e2f9bb07384c00604d1a40d0b5f62be6c.zip
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pkl/squashfs-linus
* git://git.kernel.org/pub/scm/linux/kernel/git/pkl/squashfs-linus: Squashfs: update email address Squashfs: add extra sanity checks at mount time Squashfs: add sanity checks to fragment reading at mount time Squashfs: add sanity checks to lookup table reading at mount time Squashfs: add sanity checks to id reading at mount time Squashfs: add sanity checks to xattr reading at mount time Squashfs: reverse order of filesystem table reading Squashfs: move table allocation into squashfs_read_table()
-rw-r--r--MAINTAINERS2
-rw-r--r--fs/squashfs/block.c2
-rw-r--r--fs/squashfs/cache.c31
-rw-r--r--fs/squashfs/decompressor.c2
-rw-r--r--fs/squashfs/decompressor.h2
-rw-r--r--fs/squashfs/dir.c2
-rw-r--r--fs/squashfs/export.c42
-rw-r--r--fs/squashfs/file.c2
-rw-r--r--fs/squashfs/fragment.c37
-rw-r--r--fs/squashfs/id.c42
-rw-r--r--fs/squashfs/inode.c2
-rw-r--r--fs/squashfs/namei.c2
-rw-r--r--fs/squashfs/squashfs.h10
-rw-r--r--fs/squashfs/squashfs_fs.h2
-rw-r--r--fs/squashfs/squashfs_fs_i.h2
-rw-r--r--fs/squashfs/squashfs_fs_sb.h2
-rw-r--r--fs/squashfs/super.c112
-rw-r--r--fs/squashfs/symlink.c2
-rw-r--r--fs/squashfs/xattr.c2
-rw-r--r--fs/squashfs/xattr.h3
-rw-r--r--fs/squashfs/xattr_id.c47
-rw-r--r--fs/squashfs/xz_wrapper.c2
-rw-r--r--fs/squashfs/zlib_wrapper.c2
23 files changed, 203 insertions, 151 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index d1a1465bec02..c4fc1daddcb6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6001,7 +6001,7 @@ F: Documentation/filesystems/spufs.txt
F: arch/powerpc/platforms/cell/spufs/
SQUASHFS FILE SYSTEM
-M: Phillip Lougher <phillip@lougher.demon.co.uk>
+M: Phillip Lougher <phillip@squashfs.org.uk>
L: squashfs-devel@lists.sourceforge.net (subscribers-only)
W: http://squashfs.org.uk
S: Maintained
diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c
index 8ab48bc2fa7d..ed0eb2a921f4 100644
--- a/fs/squashfs/block.c
+++ b/fs/squashfs/block.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
diff --git a/fs/squashfs/cache.c b/fs/squashfs/cache.c
index 4b5a3fbb1f1f..f744be98cd5a 100644
--- a/fs/squashfs/cache.c
+++ b/fs/squashfs/cache.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
@@ -393,19 +393,36 @@ struct squashfs_cache_entry *squashfs_get_datablock(struct super_block *sb,
/*
* Read a filesystem table (uncompressed sequence of bytes) from disk
*/
-int squashfs_read_table(struct super_block *sb, void *buffer, u64 block,
- int length)
+void *squashfs_read_table(struct super_block *sb, u64 block, int length)
{
int pages = (length + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
int i, res;
- void **data = kcalloc(pages, sizeof(void *), GFP_KERNEL);
- if (data == NULL)
- return -ENOMEM;
+ void *table, *buffer, **data;
+
+ table = buffer = kmalloc(length, GFP_KERNEL);
+ if (table == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ data = kcalloc(pages, sizeof(void *), GFP_KERNEL);
+ if (data == NULL) {
+ res = -ENOMEM;
+ goto failed;
+ }
for (i = 0; i < pages; i++, buffer += PAGE_CACHE_SIZE)
data[i] = buffer;
+
res = squashfs_read_data(sb, data, block, length |
SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length, pages);
+
kfree(data);
- return res;
+
+ if (res < 0)
+ goto failed;
+
+ return table;
+
+failed:
+ kfree(table);
+ return ERR_PTR(res);
}
diff --git a/fs/squashfs/decompressor.c b/fs/squashfs/decompressor.c
index e921bd213738..9f1b0bb96f13 100644
--- a/fs/squashfs/decompressor.c
+++ b/fs/squashfs/decompressor.c
@@ -2,7 +2,7 @@
* Squashfs - a compressed read only filesystem for Linux
*
* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
- * 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
diff --git a/fs/squashfs/decompressor.h b/fs/squashfs/decompressor.h
index 099745ad5691..8ba70cff09a6 100644
--- a/fs/squashfs/decompressor.h
+++ b/fs/squashfs/decompressor.h
@@ -4,7 +4,7 @@
* Squashfs - a compressed read only filesystem for Linux
*
* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
- * 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
diff --git a/fs/squashfs/dir.c b/fs/squashfs/dir.c
index 3f79cd1d0c19..9dfe2ce0fb70 100644
--- a/fs/squashfs/dir.c
+++ b/fs/squashfs/dir.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
diff --git a/fs/squashfs/export.c b/fs/squashfs/export.c
index 7f93d5a9ee05..730c56248c9b 100644
--- a/fs/squashfs/export.c
+++ b/fs/squashfs/export.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
@@ -121,30 +121,38 @@ static struct dentry *squashfs_get_parent(struct dentry *child)
* Read uncompressed inode lookup table indexes off disk into memory
*/
__le64 *squashfs_read_inode_lookup_table(struct super_block *sb,
- u64 lookup_table_start, unsigned int inodes)
+ u64 lookup_table_start, u64 next_table, unsigned int inodes)
{
unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(inodes);
- __le64 *inode_lookup_table;
- int err;
+ __le64 *table;
TRACE("In read_inode_lookup_table, length %d\n", length);
- /* Allocate inode lookup table indexes */
- inode_lookup_table = kmalloc(length, GFP_KERNEL);
- if (inode_lookup_table == NULL) {
- ERROR("Failed to allocate inode lookup table\n");
- return ERR_PTR(-ENOMEM);
- }
+ /* Sanity check values */
+
+ /* there should always be at least one inode */
+ if (inodes == 0)
+ return ERR_PTR(-EINVAL);
+
+ /* length bytes should not extend into the next table - this check
+ * also traps instances where lookup_table_start is incorrectly larger
+ * than the next table start
+ */
+ if (lookup_table_start + length > next_table)
+ return ERR_PTR(-EINVAL);
+
+ table = squashfs_read_table(sb, lookup_table_start, length);
- err = squashfs_read_table(sb, inode_lookup_table, lookup_table_start,
- length);
- if (err < 0) {
- ERROR("unable to read inode lookup table\n");
- kfree(inode_lookup_table);
- return ERR_PTR(err);
+ /*
+ * table[0] points to the first inode lookup table metadata block,
+ * this should be less than lookup_table_start
+ */
+ if (!IS_ERR(table) && table[0] >= lookup_table_start) {
+ kfree(table);
+ return ERR_PTR(-EINVAL);
}
- return inode_lookup_table;
+ return table;
}
diff --git a/fs/squashfs/file.c b/fs/squashfs/file.c
index a25c5060bdcb..38bb1c640559 100644
--- a/fs/squashfs/file.c
+++ b/fs/squashfs/file.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
diff --git a/fs/squashfs/fragment.c b/fs/squashfs/fragment.c
index 7eef571443c6..1516a6490bfb 100644
--- a/fs/squashfs/fragment.c
+++ b/fs/squashfs/fragment.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
@@ -71,26 +71,29 @@ int squashfs_frag_lookup(struct super_block *sb, unsigned int fragment,
* Read the uncompressed fragment lookup table indexes off disk into memory
*/
__le64 *squashfs_read_fragment_index_table(struct super_block *sb,
- u64 fragment_table_start, unsigned int fragments)
+ u64 fragment_table_start, u64 next_table, unsigned int fragments)
{
unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(fragments);
- __le64 *fragment_index;
- int err;
+ __le64 *table;
- /* Allocate fragment lookup table indexes */
- fragment_index = kmalloc(length, GFP_KERNEL);
- if (fragment_index == NULL) {
- ERROR("Failed to allocate fragment index table\n");
- return ERR_PTR(-ENOMEM);
- }
+ /*
+ * Sanity check, length bytes should not extend into the next table -
+ * this check also traps instances where fragment_table_start is
+ * incorrectly larger than the next table start
+ */
+ if (fragment_table_start + length > next_table)
+ return ERR_PTR(-EINVAL);
+
+ table = squashfs_read_table(sb, fragment_table_start, length);
- err = squashfs_read_table(sb, fragment_index, fragment_table_start,
- length);
- if (err < 0) {
- ERROR("unable to read fragment index table\n");
- kfree(fragment_index);
- return ERR_PTR(err);
+ /*
+ * table[0] points to the first fragment table metadata block, this
+ * should be less than fragment_table_start
+ */
+ if (!IS_ERR(table) && table[0] >= fragment_table_start) {
+ kfree(table);
+ return ERR_PTR(-EINVAL);
}
- return fragment_index;
+ return table;
}
diff --git a/fs/squashfs/id.c b/fs/squashfs/id.c
index d8f32452638e..a70858e0fb44 100644
--- a/fs/squashfs/id.c
+++ b/fs/squashfs/id.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
@@ -66,27 +66,37 @@ int squashfs_get_id(struct super_block *sb, unsigned int index,
* Read uncompressed id lookup table indexes from disk into memory
*/
__le64 *squashfs_read_id_index_table(struct super_block *sb,
- u64 id_table_start, unsigned short no_ids)
+ u64 id_table_start, u64 next_table, unsigned short no_ids)
{
unsigned int length = SQUASHFS_ID_BLOCK_BYTES(no_ids);
- __le64 *id_table;
- int err;
+ __le64 *table;
TRACE("In read_id_index_table, length %d\n", length);
- /* Allocate id lookup table indexes */
- id_table = kmalloc(length, GFP_KERNEL);
- if (id_table == NULL) {
- ERROR("Failed to allocate id index table\n");
- return ERR_PTR(-ENOMEM);
- }
+ /* Sanity check values */
+
+ /* there should always be at least one id */
+ if (no_ids == 0)
+ return ERR_PTR(-EINVAL);
+
+ /*
+ * length bytes should not extend into the next table - this check
+ * also traps instances where id_table_start is incorrectly larger
+ * than the next table start
+ */
+ if (id_table_start + length > next_table)
+ return ERR_PTR(-EINVAL);
+
+ table = squashfs_read_table(sb, id_table_start, length);
- err = squashfs_read_table(sb, id_table, id_table_start, length);
- if (err < 0) {
- ERROR("unable to read id index table\n");
- kfree(id_table);
- return ERR_PTR(err);
+ /*
+ * table[0] points to the first id lookup table metadata block, this
+ * should be less than id_table_start
+ */
+ if (!IS_ERR(table) && table[0] >= id_table_start) {
+ kfree(table);
+ return ERR_PTR(-EINVAL);
}
- return id_table;
+ return table;
}
diff --git a/fs/squashfs/inode.c b/fs/squashfs/inode.c
index 62e63ad25075..04bebcaa2373 100644
--- a/fs/squashfs/inode.c
+++ b/fs/squashfs/inode.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
diff --git a/fs/squashfs/namei.c b/fs/squashfs/namei.c
index 5d922a6701ab..4bc63ac64bc0 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
diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h
index 1f2e608b8785..e3be6a71cfa7 100644
--- a/fs/squashfs/squashfs.h
+++ b/fs/squashfs/squashfs.h
@@ -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
@@ -44,24 +44,24 @@ extern struct squashfs_cache_entry *squashfs_get_fragment(struct super_block *,
u64, int);
extern struct squashfs_cache_entry *squashfs_get_datablock(struct super_block *,
u64, int);
-extern int squashfs_read_table(struct super_block *, void *, u64, int);
+extern void *squashfs_read_table(struct super_block *, u64, int);
/* decompressor.c */
extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int);
extern void *squashfs_decompressor_init(struct super_block *, unsigned short);
/* export.c */
-extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64,
+extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64, u64,
unsigned int);
/* fragment.c */
extern int squashfs_frag_lookup(struct super_block *, unsigned int, u64 *);
extern __le64 *squashfs_read_fragment_index_table(struct super_block *,
- u64, unsigned int);
+ u64, u64, unsigned int);
/* id.c */
extern int squashfs_get_id(struct super_block *, unsigned int, unsigned int *);
-extern __le64 *squashfs_read_id_index_table(struct super_block *, u64,
+extern __le64 *squashfs_read_id_index_table(struct super_block *, u64, u64,
unsigned short);
/* inode.c */
diff --git a/fs/squashfs/squashfs_fs.h b/fs/squashfs/squashfs_fs.h
index 4582c568ef4d..b4a4e539a08c 100644
--- a/fs/squashfs/squashfs_fs.h
+++ b/fs/squashfs/squashfs_fs.h
@@ -4,7 +4,7 @@
* Squashfs
*
* 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
diff --git a/fs/squashfs/squashfs_fs_i.h b/fs/squashfs/squashfs_fs_i.h
index 359baefc01fc..73588e7700ed 100644
--- a/fs/squashfs/squashfs_fs_i.h
+++ b/fs/squashfs/squashfs_fs_i.h
@@ -4,7 +4,7 @@
* Squashfs
*
* 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
diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h
index d9037a5215f0..651f0b31d296 100644
--- a/fs/squashfs/squashfs_fs_sb.h
+++ b/fs/squashfs/squashfs_fs_sb.h
@@ -4,7 +4,7 @@
* Squashfs
*
* 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
diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index 5c8184c061a4..6f26abee3597 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.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
@@ -83,7 +83,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
long long root_inode;
unsigned short flags;
unsigned int fragments;
- u64 lookup_table_start, xattr_id_table_start;
+ u64 lookup_table_start, xattr_id_table_start, next_table;
int err;
TRACE("Entered squashfs_fill_superblock\n");
@@ -95,12 +95,6 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
}
msblk = sb->s_fs_info;
- sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
- if (sblk == NULL) {
- ERROR("Failed to allocate squashfs_super_block\n");
- goto failure;
- }
-
msblk->devblksize = sb_min_blocksize(sb, BLOCK_SIZE);
msblk->devblksize_log2 = ffz(~msblk->devblksize);
@@ -114,10 +108,12 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
* of bytes_used) we need to set it to an initial sensible dummy value
*/
msblk->bytes_used = sizeof(*sblk);
- err = squashfs_read_table(sb, sblk, SQUASHFS_START, sizeof(*sblk));
+ sblk = squashfs_read_table(sb, SQUASHFS_START, sizeof(*sblk));
- if (err < 0) {
+ if (IS_ERR(sblk)) {
ERROR("unable to read squashfs_super_block\n");
+ err = PTR_ERR(sblk);
+ sblk = NULL;
goto failed_mount;
}
@@ -218,18 +214,61 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
goto failed_mount;
}
+ /* Handle xattrs */
+ sb->s_xattr = squashfs_xattr_handlers;
+ xattr_id_table_start = le64_to_cpu(sblk->xattr_id_table_start);
+ if (xattr_id_table_start == SQUASHFS_INVALID_BLK) {
+ next_table = msblk->bytes_used;
+ goto allocate_id_index_table;
+ }
+
+ /* Allocate and read xattr id lookup table */
+ msblk->xattr_id_table = squashfs_read_xattr_id_table(sb,
+ xattr_id_table_start, &msblk->xattr_table, &msblk->xattr_ids);
+ if (IS_ERR(msblk->xattr_id_table)) {
+ ERROR("unable to read xattr id index table\n");
+ err = PTR_ERR(msblk->xattr_id_table);
+ msblk->xattr_id_table = NULL;
+ if (err != -ENOTSUPP)
+ goto failed_mount;
+ }
+ next_table = msblk->xattr_table;
+
+allocate_id_index_table:
/* Allocate and read id index table */
msblk->id_table = squashfs_read_id_index_table(sb,
- le64_to_cpu(sblk->id_table_start), le16_to_cpu(sblk->no_ids));
+ le64_to_cpu(sblk->id_table_start), next_table,
+ le16_to_cpu(sblk->no_ids));
if (IS_ERR(msblk->id_table)) {
+ ERROR("unable to read id index table\n");
err = PTR_ERR(msblk->id_table);
msblk->id_table = NULL;
goto failed_mount;
}
+ next_table = msblk->id_table[0];
+
+ /* Handle inode lookup table */
+ lookup_table_start = le64_to_cpu(sblk->lookup_table_start);
+ if (lookup_table_start == SQUASHFS_INVALID_BLK)
+ goto handle_fragments;
+
+ /* Allocate and read inode lookup table */
+ msblk->inode_lookup_table = squashfs_read_inode_lookup_table(sb,
+ lookup_table_start, next_table, msblk->inodes);
+ if (IS_ERR(msblk->inode_lookup_table)) {
+ ERROR("unable to read inode lookup table\n");
+ err = PTR_ERR(msblk->inode_lookup_table);
+ msblk->inode_lookup_table = NULL;
+ goto failed_mount;
+ }
+ next_table = msblk->inode_lookup_table[0];
+ sb->s_export_op = &squashfs_export_ops;
+
+handle_fragments:
fragments = le32_to_cpu(sblk->fragments);
if (fragments == 0)
- goto allocate_lookup_table;
+ goto check_directory_table;
msblk->fragment_cache = squashfs_cache_init("fragment",
SQUASHFS_CACHED_FRAGMENTS, msblk->block_size);
@@ -240,45 +279,29 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
/* Allocate and read fragment index table */
msblk->fragment_index = squashfs_read_fragment_index_table(sb,
- le64_to_cpu(sblk->fragment_table_start), fragments);
+ le64_to_cpu(sblk->fragment_table_start), next_table, fragments);
if (IS_ERR(msblk->fragment_index)) {
+ ERROR("unable to read fragment index table\n");
err = PTR_ERR(msblk->fragment_index);
msblk->fragment_index = NULL;
goto failed_mount;
}
+ next_table = msblk->fragment_index[0];
-allocate_lookup_table:
- lookup_table_start = le64_to_cpu(sblk->lookup_table_start);
- if (lookup_table_start == SQUASHFS_INVALID_BLK)
- goto allocate_xattr_table;
-
- /* Allocate and read inode lookup table */
- msblk->inode_lookup_table = squashfs_read_inode_lookup_table(sb,
- lookup_table_start, msblk->inodes);
- if (IS_ERR(msblk->inode_lookup_table)) {
- err = PTR_ERR(msblk->inode_lookup_table);
- msblk->inode_lookup_table = NULL;
+check_directory_table:
+ /* Sanity check directory_table */
+ if (msblk->directory_table >= next_table) {
+ err = -EINVAL;
goto failed_mount;
}
- sb->s_export_op = &squashfs_export_ops;
-
-allocate_xattr_table:
- sb->s_xattr = squashfs_xattr_handlers;
- xattr_id_table_start = le64_to_cpu(sblk->xattr_id_table_start);
- if (xattr_id_table_start == SQUASHFS_INVALID_BLK)
- goto allocate_root;
-
- /* Allocate and read xattr id lookup table */
- msblk->xattr_id_table = squashfs_read_xattr_id_table(sb,
- xattr_id_table_start, &msblk->xattr_table, &msblk->xattr_ids);
- if (IS_ERR(msblk->xattr_id_table)) {
- err = PTR_ERR(msblk->xattr_id_table);
- msblk->xattr_id_table = NULL;
- if (err != -ENOTSUPP)
- goto failed_mount;
+ /* Sanity check inode_table */
+ if (msblk->inode_table >= msblk->directory_table) {
+ err = -EINVAL;
+ goto failed_mount;
}
-allocate_root:
+
+ /* allocate root */
root = new_inode(sb);
if (!root) {
err = -ENOMEM;
@@ -318,11 +341,6 @@ failed_mount:
sb->s_fs_info = NULL;
kfree(sblk);
return err;
-
-failure:
- kfree(sb->s_fs_info);
- sb->s_fs_info = NULL;
- return -ENOMEM;
}
@@ -475,5 +493,5 @@ static const struct super_operations squashfs_super_ops = {
module_init(init_squashfs_fs);
module_exit(exit_squashfs_fs);
MODULE_DESCRIPTION("squashfs 4.0, a compressed read-only filesystem");
-MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>");
+MODULE_AUTHOR("Phillip Lougher <phillip@squashfs.org.uk>");
MODULE_LICENSE("GPL");
diff --git a/fs/squashfs/symlink.c b/fs/squashfs/symlink.c
index ec86434921e1..1191817264cc 100644
--- a/fs/squashfs/symlink.c
+++ b/fs/squashfs/symlink.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
diff --git a/fs/squashfs/xattr.c b/fs/squashfs/xattr.c
index 3876c36699a1..92fcde7b4d61 100644
--- a/fs/squashfs/xattr.c
+++ b/fs/squashfs/xattr.c
@@ -2,7 +2,7 @@
* Squashfs - a compressed read only filesystem for Linux
*
* Copyright (c) 2010
- * 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
diff --git a/fs/squashfs/xattr.h b/fs/squashfs/xattr.h
index b634efce4bde..c83f5d9ec125 100644
--- a/fs/squashfs/xattr.h
+++ b/fs/squashfs/xattr.h
@@ -2,7 +2,7 @@
* Squashfs - a compressed read only filesystem for Linux
*
* Copyright (c) 2010
- * 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
@@ -31,6 +31,7 @@ static inline __le64 *squashfs_read_xattr_id_table(struct super_block *sb,
u64 start, u64 *xattr_table_start, int *xattr_ids)
{
ERROR("Xattrs in filesystem, these will be ignored\n");
+ *xattr_table_start = start;
return ERR_PTR(-ENOTSUPP);
}
diff --git a/fs/squashfs/xattr_id.c b/fs/squashfs/xattr_id.c
index 05385dbe1465..c89607d690c4 100644
--- a/fs/squashfs/xattr_id.c
+++ b/fs/squashfs/xattr_id.c
@@ -2,7 +2,7 @@
* Squashfs - a compressed read only filesystem for Linux
*
* Copyright (c) 2010
- * 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
@@ -67,34 +67,29 @@ __le64 *squashfs_read_xattr_id_table(struct super_block *sb, u64 start,
u64 *xattr_table_start, int *xattr_ids)
{
unsigned int len;
- __le64 *xid_table;
- struct squashfs_xattr_id_table id_table;
- int err;
+ struct squashfs_xattr_id_table *id_table;
+
+ id_table = squashfs_read_table(sb, start, sizeof(*id_table));
+ if (IS_ERR(id_table))
+ return (__le64 *) id_table;
+
+ *xattr_table_start = le64_to_cpu(id_table->xattr_table_start);
+ *xattr_ids = le32_to_cpu(id_table->xattr_ids);
+ kfree(id_table);
+
+ /* Sanity check values */
+
+ /* there is always at least one xattr id */
+ if (*xattr_ids == 0)
+ return ERR_PTR(-EINVAL);
+
+ /* xattr_table should be less than start */
+ if (*xattr_table_start >= start)
+ return ERR_PTR(-EINVAL);
- err = squashfs_read_table(sb, &id_table, start, sizeof(id_table));
- if (err < 0) {
- ERROR("unable to read xattr id table\n");
- return ERR_PTR(err);
- }
- *xattr_table_start = le64_to_cpu(id_table.xattr_table_start);
- *xattr_ids = le32_to_cpu(id_table.xattr_ids);
len = SQUASHFS_XATTR_BLOCK_BYTES(*xattr_ids);
TRACE("In read_xattr_index_table, length %d\n", len);
- /* Allocate xattr id lookup table indexes */
- xid_table = kmalloc(len, GFP_KERNEL);
- if (xid_table == NULL) {
- ERROR("Failed to allocate xattr id index table\n");
- return ERR_PTR(-ENOMEM);
- }
-
- err = squashfs_read_table(sb, xid_table, start + sizeof(id_table), len);
- if (err < 0) {
- ERROR("unable to read xattr id index table\n");
- kfree(xid_table);
- return ERR_PTR(err);
- }
-
- return xid_table;
+ return squashfs_read_table(sb, start + sizeof(*id_table), len);
}
diff --git a/fs/squashfs/xz_wrapper.c b/fs/squashfs/xz_wrapper.c
index aa47a286d1f8..1760b7d108f6 100644
--- a/fs/squashfs/xz_wrapper.c
+++ b/fs/squashfs/xz_wrapper.c
@@ -2,7 +2,7 @@
* Squashfs - a compressed read only filesystem for Linux
*
* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
- * 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
diff --git a/fs/squashfs/zlib_wrapper.c b/fs/squashfs/zlib_wrapper.c
index 517688b32ffa..55d918fd2d86 100644
--- a/fs/squashfs/zlib_wrapper.c
+++ b/fs/squashfs/zlib_wrapper.c
@@ -2,7 +2,7 @@
* Squashfs - a compressed read only filesystem for Linux
*
* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
- * 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