From: Joao Marcos Costa <joaomarcos.co...@bootlin.com> The length of buffers used to read inode tables, directory tables, and reading a file are calculated as: number of blocks * block size, and such plain multiplication is prone to overflowing (thus unsafe).
Replace it by __builtin_mul_overflow, i.e. safe math. Signed-off-by: Joao Marcos Costa <joaomarcos.co...@bootlin.com> --- fs/squashfs/sqfs.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/fs/squashfs/sqfs.c b/fs/squashfs/sqfs.c index b9314019b1b..8fac6c6c5a9 100644 --- a/fs/squashfs/sqfs.c +++ b/fs/squashfs/sqfs.c @@ -719,6 +719,7 @@ static int sqfs_read_inode_table(unsigned char **inode_table) u32 src_len, dest_offset = 0; unsigned long dest_len = 0; bool compressed; + size_t buf_size; table_size = get_unaligned_le64(&sblk->directory_table_start) - get_unaligned_le64(&sblk->inode_table_start); @@ -728,7 +729,10 @@ static int sqfs_read_inode_table(unsigned char **inode_table) sblk->directory_table_start, &table_offset); /* Allocate a proper sized buffer (itb) to store the inode table */ - itb = malloc_cache_aligned(n_blks * ctxt.cur_dev->blksz); + if (__builtin_mul_overflow(n_blks, ctxt.cur_dev->blksz, &buf_size)) + return -EINVAL; + + itb = malloc_cache_aligned(buf_size); if (!itb) return -ENOMEM; @@ -806,6 +810,7 @@ static int sqfs_read_directory_table(unsigned char **dir_table, u32 **pos_list) u32 src_len, dest_offset = 0; unsigned long dest_len = 0; bool compressed; + size_t buf_size; *dir_table = NULL; *pos_list = NULL; @@ -818,7 +823,10 @@ static int sqfs_read_directory_table(unsigned char **dir_table, u32 **pos_list) sblk->fragment_table_start, &table_offset); /* Allocate a proper sized buffer (dtb) to store the directory table */ - dtb = malloc_cache_aligned(n_blks * ctxt.cur_dev->blksz); + if (__builtin_mul_overflow(n_blks, ctxt.cur_dev->blksz, &buf_size)) + return -EINVAL; + + dtb = malloc_cache_aligned(buf_size); if (!dtb) return -ENOMEM; @@ -1369,6 +1377,7 @@ static int sqfs_read_nest(const char *filename, void *buf, loff_t offset, unsigned long dest_len; struct fs_dirent *dent; unsigned char *ipos; + size_t buf_size; *actread = 0; @@ -1573,7 +1582,10 @@ static int sqfs_read_nest(const char *filename, void *buf, loff_t offset, table_offset = frag_entry.start - (start * ctxt.cur_dev->blksz); n_blks = DIV_ROUND_UP(table_size + table_offset, ctxt.cur_dev->blksz); - fragment = malloc_cache_aligned(n_blks * ctxt.cur_dev->blksz); + if (__builtin_mul_overflow(n_blks, ctxt.cur_dev->blksz, &buf_size)) + return -EINVAL; + + fragment = malloc_cache_aligned(buf_size); if (!fragment) { ret = -ENOMEM; -- 2.47.0