Skip to content

Commit 72dc245

Browse files
torvaldsZhengShunQian
authored andcommitted
squashfs: more metadata hardenings
commit 71755ee upstream. The squashfs fragment reading code doesn't actually verify that the fragment is inside the fragment table. The end result _is_ verified to be inside the image when actually reading the fragment data, but before that is done, we may end up taking a page fault because the fragment table itself might not even exist. Another report from Anatoly and his endless squashfs image fuzzing. Reported-by: Анатолий Тросиненко <[email protected]> Acked-by:: Phillip Lougher <[email protected]>, Cc: Willy Tarreau <[email protected]> Signed-off-by: Linus Torvalds <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent bb5899c commit 72dc245

File tree

3 files changed

+13
-6
lines changed

3 files changed

+13
-6
lines changed

fs/squashfs/fragment.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,16 @@ int squashfs_frag_lookup(struct super_block *sb, unsigned int fragment,
4949
u64 *fragment_block)
5050
{
5151
struct squashfs_sb_info *msblk = sb->s_fs_info;
52-
int block = SQUASHFS_FRAGMENT_INDEX(fragment);
53-
int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);
54-
u64 start_block = le64_to_cpu(msblk->fragment_index[block]);
52+
int block, offset, size;
5553
struct squashfs_fragment_entry fragment_entry;
56-
int size;
54+
u64 start_block;
55+
56+
if (fragment >= msblk->fragments)
57+
return -EIO;
58+
block = SQUASHFS_FRAGMENT_INDEX(fragment);
59+
offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);
60+
61+
start_block = le64_to_cpu(msblk->fragment_index[block]);
5762

5863
size = squashfs_read_metadata(sb, &fragment_entry, &start_block,
5964
&offset, sizeof(fragment_entry));

fs/squashfs/squashfs_fs_sb.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ struct squashfs_sb_info {
7575
unsigned short block_log;
7676
long long bytes_used;
7777
unsigned int inodes;
78+
unsigned int fragments;
7879
int xattr_ids;
7980
};
8081
#endif

fs/squashfs/super.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
176176
msblk->inode_table = le64_to_cpu(sblk->inode_table_start);
177177
msblk->directory_table = le64_to_cpu(sblk->directory_table_start);
178178
msblk->inodes = le32_to_cpu(sblk->inodes);
179+
msblk->fragments = le32_to_cpu(sblk->fragments);
179180
flags = le16_to_cpu(sblk->flags);
180181

181182
TRACE("Found valid superblock on %s\n", bdevname(sb->s_bdev, b));
@@ -186,7 +187,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
186187
TRACE("Filesystem size %lld bytes\n", msblk->bytes_used);
187188
TRACE("Block size %d\n", msblk->block_size);
188189
TRACE("Number of inodes %d\n", msblk->inodes);
189-
TRACE("Number of fragments %d\n", le32_to_cpu(sblk->fragments));
190+
TRACE("Number of fragments %d\n", msblk->fragments);
190191
TRACE("Number of ids %d\n", le16_to_cpu(sblk->no_ids));
191192
TRACE("sblk->inode_table_start %llx\n", msblk->inode_table);
192193
TRACE("sblk->directory_table_start %llx\n", msblk->directory_table);
@@ -273,7 +274,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
273274
sb->s_export_op = &squashfs_export_ops;
274275

275276
handle_fragments:
276-
fragments = le32_to_cpu(sblk->fragments);
277+
fragments = msblk->fragments;
277278
if (fragments == 0)
278279
goto check_directory_table;
279280

0 commit comments

Comments
 (0)