diff options
Diffstat (limited to 'fs/squashfs/export.c')
-rw-r--r-- | fs/squashfs/export.c | 42 |
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 | ||