struct squashfs_sb_info *msblk = sb->s_fs_info;
        int block = SQUASHFS_ID_BLOCK(index);
        int offset = SQUASHFS_ID_BLOCK_OFFSET(index);
-       u64 start_block = le64_to_cpu(msblk->id_table[block]);
+       u64 start_block;
        __le32 disk_id;
        int err;
 
+       if (index >= msblk->ids)
+               return -EINVAL;
+
+       start_block = le64_to_cpu(msblk->id_table[block]);
+
        err = squashfs_read_metadata(sb, &disk_id, &start_block, &offset,
                                                        sizeof(disk_id));
        if (err < 0)
                u64 id_table_start, u64 next_table, unsigned short no_ids)
 {
        unsigned int length = SQUASHFS_ID_BLOCK_BYTES(no_ids);
+       unsigned int indexes = SQUASHFS_ID_BLOCKS(no_ids);
+       int n;
        __le64 *table;
+       u64 start, end;
 
        TRACE("In read_id_index_table, length %d\n", length);
 
                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
+        * The computed size of the index table (length bytes) should exactly
+        * match the table start and end points
         */
-       if (id_table_start + length > next_table)
+       if (length != (next_table - id_table_start))
                return ERR_PTR(-EINVAL);
 
        table = squashfs_read_table(sb, id_table_start, length);
+       if (IS_ERR(table))
+               return table;
 
        /*
-        * table[0] points to the first id lookup table metadata block, this
-        * should be less than id_table_start
+        * table[0], table[1], ... table[indexes - 1] store the locations
+        * of the compressed id blocks.   Each entry should be less than
+        * the next (i.e. table[0] < table[1]), and the difference between them
+        * should be SQUASHFS_METADATA_SIZE or less.  table[indexes - 1]
+        * should be less than id_table_start, and again the difference
+        * should be SQUASHFS_METADATA_SIZE or less
         */
-       if (!IS_ERR(table) && le64_to_cpu(table[0]) >= id_table_start) {
+       for (n = 0; n < (indexes - 1); n++) {
+               start = le64_to_cpu(table[n]);
+               end = le64_to_cpu(table[n + 1]);
+
+               if (start >= end || (end - start) > SQUASHFS_METADATA_SIZE) {
+                       kfree(table);
+                       return ERR_PTR(-EINVAL);
+               }
+       }
+
+       start = le64_to_cpu(table[indexes - 1]);
+       if (start >= id_table_start || (id_table_start - start) > SQUASHFS_METADATA_SIZE) {
                kfree(table);
                return ERR_PTR(-EINVAL);
        }
 
        msblk->directory_table = le64_to_cpu(sblk->directory_table_start);
        msblk->inodes = le32_to_cpu(sblk->inodes);
        msblk->fragments = le32_to_cpu(sblk->fragments);
+       msblk->ids = le16_to_cpu(sblk->no_ids);
        flags = le16_to_cpu(sblk->flags);
 
        TRACE("Found valid superblock on %pg\n", sb->s_bdev);
        TRACE("Block size %d\n", msblk->block_size);
        TRACE("Number of inodes %d\n", msblk->inodes);
        TRACE("Number of fragments %d\n", msblk->fragments);
-       TRACE("Number of ids %d\n", le16_to_cpu(sblk->no_ids));
+       TRACE("Number of ids %d\n", msblk->ids);
        TRACE("sblk->inode_table_start %llx\n", msblk->inode_table);
        TRACE("sblk->directory_table_start %llx\n", msblk->directory_table);
        TRACE("sblk->fragment_table_start %llx\n",
 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), next_table,
-               le16_to_cpu(sblk->no_ids));
+               le64_to_cpu(sblk->id_table_start), next_table, msblk->ids);
        if (IS_ERR(msblk->id_table)) {
                errorf(fc, "unable to read id index table");
                err = PTR_ERR(msblk->id_table);
 
 static inline __le64 *squashfs_read_xattr_id_table(struct super_block *sb,
                u64 start, u64 *xattr_table_start, int *xattr_ids)
 {
+       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);
+       kfree(id_table);
+
        ERROR("Xattrs in filesystem, these will be ignored\n");
-       *xattr_table_start = start;
        return ERR_PTR(-ENOTSUPP);
 }