diff options
author | Joao Marcos Costa <joaomarcos.costa@bootlin.com> | 2025-02-19 11:16:33 +0100 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2025-02-24 08:49:04 -0600 |
commit | 59fd62d71c6a04b3ab9db848414a7c386cfd2cfb (patch) | |
tree | e30a0d341111f0eb8cae3dd52c2f18ca02bfd2a7 | |
parent | 5061eab96acd60d28149e080f3a37fbe7220ca54 (diff) |
fs/squashfs: fix potential integer overflows
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.costa@bootlin.com>
-rw-r--r-- | fs/squashfs/sqfs.c | 18 |
1 files 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; |