Fix defects such as uninitialized variables and untrusted pointer
operations. Most part of the tainted variables and the related defects
actually comes from Linux's macro get_unaligned_le**, extensively used
in SquashFS code. Add sanity checks for those variables.
Signed-off-by: Joao Marcos Costa <joaomarcos.costa@bootlin.com>
header = get_unaligned_le16(metadata_buffer + table_offset);
metadata = metadata_buffer + table_offset + SQFS_HEADER_SIZE;
header = get_unaligned_le16(metadata_buffer + table_offset);
metadata = metadata_buffer + table_offset + SQFS_HEADER_SIZE;
+ if (!metadata) {
+ ret = -ENOMEM;
+ goto free_buffer;
+ }
+
entries = malloc(SQFS_METADATA_BLOCK_SIZE);
if (!entries) {
ret = -ENOMEM;
entries = malloc(SQFS_METADATA_BLOCK_SIZE);
if (!entries) {
ret = -ENOMEM;
*/
static int sqfs_tokenize(char **tokens, int count, const char *str)
{
*/
static int sqfs_tokenize(char **tokens, int count, const char *str)
{
strc = strdup(str);
if (!strc)
strc = strdup(str);
if (!strc)
if (!strcmp(strc, "/")) {
tokens[0] = strdup(strc);
if (!tokens[0]) {
if (!strcmp(strc, "/")) {
tokens[0] = strdup(strc);
if (!tokens[0]) {
- free(strc);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto free_strc;
}
} else {
for (j = 0; j < count; j++) {
}
} else {
for (j = 0; j < count; j++) {
if (!tokens[j]) {
for (i = 0; i < j; i++)
free(tokens[i]);
if (!tokens[j]) {
for (i = 0; i < j; i++)
free(tokens[i]);
- free(strc);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto free_strc;
{
struct squashfs_super_block *sblk = ctxt.sblk;
char *path, *target, **sym_tokens, *res, *rem;
{
struct squashfs_super_block *sblk = ctxt.sblk;
char *path, *target, **sym_tokens, *res, *rem;
+ struct squashfs_ldir_inode *ldir = NULL;
int j, ret, new_inode_number, offset;
struct squashfs_symlink_inode *sym;
int j, ret, new_inode_number, offset;
struct squashfs_symlink_inode *sym;
- struct squashfs_ldir_inode *ldir;
struct squashfs_dir_inode *dir;
struct fs_dir_stream *dirsp;
struct fs_dirent *dent;
struct squashfs_dir_inode *dir;
struct fs_dir_stream *dirsp;
struct fs_dirent *dent;
int j, ret = 0, metablks_count;
unsigned char *src_table, *itb;
u32 src_len, dest_offset = 0;
int j, ret = 0, metablks_count;
unsigned char *src_table, *itb;
u32 src_len, dest_offset = 0;
- unsigned long dest_len;
+ unsigned long dest_len = 0;
bool compressed;
table_size = get_unaligned_le64(&sblk->directory_table_start) -
bool compressed;
table_size = get_unaligned_le64(&sblk->directory_table_start) -
+ dest_offset += dest_len;
} else {
memcpy(*inode_table + (j * SQFS_METADATA_BLOCK_SIZE),
src_table, src_len);
} else {
memcpy(*inode_table + (j * SQFS_METADATA_BLOCK_SIZE),
src_table, src_len);
* Offsets to the decompression destination, to the metadata
* buffer 'itb' and to the decompression source, respectively.
*/
* Offsets to the decompression destination, to the metadata
* buffer 'itb' and to the decompression source, respectively.
*/
- dest_offset += dest_len;
table_offset += src_len + SQFS_HEADER_SIZE;
src_table += src_len + SQFS_HEADER_SIZE;
}
table_offset += src_len + SQFS_HEADER_SIZE;
src_table += src_len + SQFS_HEADER_SIZE;
}
int j, ret = 0, metablks_count = -1;
unsigned char *src_table, *dtb;
u32 src_len, dest_offset = 0;
int j, ret = 0, metablks_count = -1;
unsigned char *src_table, *dtb;
u32 src_len, dest_offset = 0;
- unsigned long dest_len;
+ unsigned long dest_len = 0;
bool compressed;
/* DIRECTORY TABLE */
bool compressed;
/* DIRECTORY TABLE */
dest_offset += dest_len;
break;
}
dest_offset += dest_len;
break;
}
+
+ dest_offset += dest_len;
} else {
memcpy(*dir_table + (j * SQFS_METADATA_BLOCK_SIZE),
src_table, src_len);
} else {
memcpy(*dir_table + (j * SQFS_METADATA_BLOCK_SIZE),
src_table, src_len);
* Offsets to the decompression destination, to the metadata
* buffer 'dtb' and to the decompression source, respectively.
*/
* Offsets to the decompression destination, to the metadata
* buffer 'dtb' and to the decompression source, respectively.
*/
- dest_offset += dest_len;
table_offset += src_len + SQFS_HEADER_SIZE;
src_table += src_len + SQFS_HEADER_SIZE;
}
table_offset += src_len + SQFS_HEADER_SIZE;
src_table += src_len + SQFS_HEADER_SIZE;
}
finfo->start = get_unaligned_le32(®->start_block);
finfo->frag = SQFS_IS_FRAGMENTED(get_unaligned_le32(®->fragment));
finfo->start = get_unaligned_le32(®->start_block);
finfo->frag = SQFS_IS_FRAGMENTED(get_unaligned_le32(®->fragment));
+ if (finfo->size < 1 || finfo->offset < 0 || finfo->start < 0)
+ return -EINVAL;
+
if (finfo->frag) {
datablk_count = finfo->size / le32_to_cpu(blksz);
ret = sqfs_frag_lookup(get_unaligned_le32(®->fragment),
if (finfo->frag) {
datablk_count = finfo->size / le32_to_cpu(blksz);
ret = sqfs_frag_lookup(get_unaligned_le32(®->fragment),
if (ret < 0)
return -EINVAL;
finfo->comp = true;
if (ret < 0)
return -EINVAL;
finfo->comp = true;
+ if (fentry->size < 1 || fentry->start < 0)
+ return -EINVAL;
} else {
datablk_count = DIV_ROUND_UP(finfo->size, le32_to_cpu(blksz));
}
} else {
datablk_count = DIV_ROUND_UP(finfo->size, le32_to_cpu(blksz));
}
finfo->start = get_unaligned_le64(&lreg->start_block);
finfo->frag = SQFS_IS_FRAGMENTED(get_unaligned_le32(&lreg->fragment));
finfo->start = get_unaligned_le64(&lreg->start_block);
finfo->frag = SQFS_IS_FRAGMENTED(get_unaligned_le32(&lreg->fragment));
+ if (finfo->size < 1 || finfo->offset < 0 || finfo->start < 0)
+ return -EINVAL;
+
if (finfo->frag) {
datablk_count = finfo->size / le32_to_cpu(blksz);
ret = sqfs_frag_lookup(get_unaligned_le32(&lreg->fragment),
if (finfo->frag) {
datablk_count = finfo->size / le32_to_cpu(blksz);
ret = sqfs_frag_lookup(get_unaligned_le32(&lreg->fragment),
if (ret < 0)
return -EINVAL;
finfo->comp = true;
if (ret < 0)
return -EINVAL;
finfo->comp = true;
+ if (fentry->size < 1 || fentry->start < 0)
+ return -EINVAL;
} else {
datablk_count = DIV_ROUND_UP(finfo->size, le32_to_cpu(blksz));
}
} else {
datablk_count = DIV_ROUND_UP(finfo->size, le32_to_cpu(blksz));
}
+ if (offset < 0)
+ return -EINVAL;
+
for (j = 0; j < m_count; j++) {
if (m_list[j] == start_block)
return (++j * SQFS_METADATA_BLOCK_SIZE) + offset;
for (j = 0; j < m_count; j++) {
if (m_list[j] == start_block)
return (++j * SQFS_METADATA_BLOCK_SIZE) + offset;
int sqfs_read_metablock(unsigned char *file_mapping, int offset,
bool *compressed, u32 *data_size)
{
int sqfs_read_metablock(unsigned char *file_mapping, int offset,
bool *compressed, u32 *data_size)
{
+ const unsigned char *data;
u16 header;
data = file_mapping + offset;
header = get_unaligned((u16 *)data);
u16 header;
data = file_mapping + offset;
header = get_unaligned((u16 *)data);
+ if (!header || !data)
+ return -EINVAL;
+
*compressed = SQFS_COMPRESSED_METADATA(header);
*data_size = SQFS_METADATA_SIZE(header);
*compressed = SQFS_COMPRESSED_METADATA(header);
*data_size = SQFS_METADATA_SIZE(header);