aboutsummaryrefslogtreecommitdiffstats
path: root/fs/squashfs/export.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/squashfs/export.c')
-rw-r--r--fs/squashfs/export.c42
1 files changed, 25 insertions, 17 deletions
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 @@
2 * Squashfs - a compressed read only filesystem for Linux 2 * Squashfs - a compressed read only filesystem for Linux
3 * 3 *
4 * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 4 * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
5 * Phillip Lougher <phillip@lougher.demon.co.uk> 5 * Phillip Lougher <phillip@squashfs.org.uk>
6 * 6 *
7 * This program is free software; you can redistribute it and/or 7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License 8 * modify it under the terms of the GNU General Public License
@@ -121,30 +121,38 @@ static struct dentry *squashfs_get_parent(struct dentry *child)
121 * Read uncompressed inode lookup table indexes off disk into memory 121 * Read uncompressed inode lookup table indexes off disk into memory
122 */ 122 */
123__le64 *squashfs_read_inode_lookup_table(struct super_block *sb, 123__le64 *squashfs_read_inode_lookup_table(struct super_block *sb,
124 u64 lookup_table_start, unsigned int inodes) 124 u64 lookup_table_start, u64 next_table, unsigned int inodes)
125{ 125{
126 unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(inodes); 126 unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(inodes);
127 __le64 *inode_lookup_table; 127 __le64 *table;
128 int err;
129 128
130 TRACE("In read_inode_lookup_table, length %d\n", length); 129 TRACE("In read_inode_lookup_table, length %d\n", length);
131 130
132 /* Allocate inode lookup table indexes */ 131 /* Sanity check values */
133 inode_lookup_table = kmalloc(length, GFP_KERNEL); 132
134 if (inode_lookup_table == NULL) { 133 /* there should always be at least one inode */
135 ERROR("Failed to allocate inode lookup table\n"); 134 if (inodes == 0)
136 return ERR_PTR(-ENOMEM); 135 return ERR_PTR(-EINVAL);
137 } 136
137 /* length bytes should not extend into the next table - this check
138 * also traps instances where lookup_table_start is incorrectly larger
139 * than the next table start
140 */
141 if (lookup_table_start + length > next_table)
142 return ERR_PTR(-EINVAL);
143
144 table = squashfs_read_table(sb, lookup_table_start, length);
138 145
139 err = squashfs_read_table(sb, inode_lookup_table, lookup_table_start, 146 /*
140 length); 147 * table[0] points to the first inode lookup table metadata block,
141 if (err < 0) { 148 * this should be less than lookup_table_start
142 ERROR("unable to read inode lookup table\n"); 149 */
143 kfree(inode_lookup_table); 150 if (!IS_ERR(table) && table[0] >= lookup_table_start) {
144 return ERR_PTR(err); 151 kfree(table);
152 return ERR_PTR(-EINVAL);
145 } 153 }
146 154
147 return inode_lookup_table; 155 return table;
148} 156}
149 157
150 158