diff options
Diffstat (limited to 'fs/squashfs/id.c')
-rw-r--r-- | fs/squashfs/id.c | 42 |
1 files changed, 26 insertions, 16 deletions
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; } |