mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-28 15:41:40 +00:00
fs/squashfs: Fix Coverity Scan defects
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>
This commit is contained in:
parent
6b0ddd1fbc
commit
c9875a5fe8
3 changed files with 36 additions and 12 deletions
|
@ -154,6 +154,11 @@ static int sqfs_frag_lookup(u32 inode_fragment_index,
|
||||||
header = get_unaligned_le16(metadata_buffer + table_offset);
|
header = get_unaligned_le16(metadata_buffer + table_offset);
|
||||||
metadata = metadata_buffer + table_offset + SQFS_HEADER_SIZE;
|
metadata = metadata_buffer + table_offset + SQFS_HEADER_SIZE;
|
||||||
|
|
||||||
|
if (!metadata) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto free_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
entries = malloc(SQFS_METADATA_BLOCK_SIZE);
|
entries = malloc(SQFS_METADATA_BLOCK_SIZE);
|
||||||
if (!entries) {
|
if (!entries) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
@ -272,8 +277,8 @@ static int sqfs_join(char **strings, char *dest, int start, int end,
|
||||||
*/
|
*/
|
||||||
static int sqfs_tokenize(char **tokens, int count, const char *str)
|
static int sqfs_tokenize(char **tokens, int count, const char *str)
|
||||||
{
|
{
|
||||||
|
int i, j, ret = 0;
|
||||||
char *aux, *strc;
|
char *aux, *strc;
|
||||||
int i, j;
|
|
||||||
|
|
||||||
strc = strdup(str);
|
strc = strdup(str);
|
||||||
if (!strc)
|
if (!strc)
|
||||||
|
@ -282,8 +287,8 @@ static int sqfs_tokenize(char **tokens, int count, const char *str)
|
||||||
if (!strcmp(strc, "/")) {
|
if (!strcmp(strc, "/")) {
|
||||||
tokens[0] = strdup(strc);
|
tokens[0] = strdup(strc);
|
||||||
if (!tokens[0]) {
|
if (!tokens[0]) {
|
||||||
free(strc);
|
ret = -ENOMEM;
|
||||||
return -ENOMEM;
|
goto free_strc;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (j = 0; j < count; j++) {
|
for (j = 0; j < count; j++) {
|
||||||
|
@ -292,15 +297,16 @@ static int sqfs_tokenize(char **tokens, int count, const char *str)
|
||||||
if (!tokens[j]) {
|
if (!tokens[j]) {
|
||||||
for (i = 0; i < j; i++)
|
for (i = 0; i < j; i++)
|
||||||
free(tokens[i]);
|
free(tokens[i]);
|
||||||
free(strc);
|
ret = -ENOMEM;
|
||||||
return -ENOMEM;
|
goto free_strc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free_strc:
|
||||||
free(strc);
|
free(strc);
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -428,9 +434,9 @@ static int sqfs_search_dir(struct squashfs_dir_stream *dirs, char **token_list,
|
||||||
{
|
{
|
||||||
struct squashfs_super_block *sblk = ctxt.sblk;
|
struct squashfs_super_block *sblk = ctxt.sblk;
|
||||||
char *path, *target, **sym_tokens, *res, *rem;
|
char *path, *target, **sym_tokens, *res, *rem;
|
||||||
|
struct squashfs_ldir_inode *ldir = NULL;
|
||||||
int j, ret, new_inode_number, offset;
|
int j, ret, new_inode_number, offset;
|
||||||
struct squashfs_symlink_inode *sym;
|
struct squashfs_symlink_inode *sym;
|
||||||
struct squashfs_ldir_inode *ldir;
|
|
||||||
struct squashfs_dir_inode *dir;
|
struct squashfs_dir_inode *dir;
|
||||||
struct fs_dir_stream *dirsp;
|
struct fs_dir_stream *dirsp;
|
||||||
struct fs_dirent *dent;
|
struct fs_dirent *dent;
|
||||||
|
@ -630,7 +636,7 @@ static int sqfs_read_inode_table(unsigned char **inode_table)
|
||||||
int j, ret = 0, metablks_count;
|
int j, ret = 0, metablks_count;
|
||||||
unsigned char *src_table, *itb;
|
unsigned char *src_table, *itb;
|
||||||
u32 src_len, dest_offset = 0;
|
u32 src_len, dest_offset = 0;
|
||||||
unsigned long dest_len;
|
unsigned long dest_len = 0;
|
||||||
bool compressed;
|
bool compressed;
|
||||||
|
|
||||||
table_size = get_unaligned_le64(&sblk->directory_table_start) -
|
table_size = get_unaligned_le64(&sblk->directory_table_start) -
|
||||||
|
@ -685,6 +691,7 @@ static int sqfs_read_inode_table(unsigned char **inode_table)
|
||||||
goto free_itb;
|
goto free_itb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dest_offset += dest_len;
|
||||||
} else {
|
} else {
|
||||||
memcpy(*inode_table + (j * SQFS_METADATA_BLOCK_SIZE),
|
memcpy(*inode_table + (j * SQFS_METADATA_BLOCK_SIZE),
|
||||||
src_table, src_len);
|
src_table, src_len);
|
||||||
|
@ -694,7 +701,7 @@ static int sqfs_read_inode_table(unsigned char **inode_table)
|
||||||
* Offsets to the decompression destination, to the metadata
|
* Offsets to the decompression destination, to the metadata
|
||||||
* buffer 'itb' and to the decompression source, respectively.
|
* buffer 'itb' and to the decompression source, respectively.
|
||||||
*/
|
*/
|
||||||
dest_offset += dest_len;
|
|
||||||
table_offset += src_len + SQFS_HEADER_SIZE;
|
table_offset += src_len + SQFS_HEADER_SIZE;
|
||||||
src_table += src_len + SQFS_HEADER_SIZE;
|
src_table += src_len + SQFS_HEADER_SIZE;
|
||||||
}
|
}
|
||||||
|
@ -712,7 +719,7 @@ static int sqfs_read_directory_table(unsigned char **dir_table, u32 **pos_list)
|
||||||
int j, ret = 0, metablks_count = -1;
|
int j, ret = 0, metablks_count = -1;
|
||||||
unsigned char *src_table, *dtb;
|
unsigned char *src_table, *dtb;
|
||||||
u32 src_len, dest_offset = 0;
|
u32 src_len, dest_offset = 0;
|
||||||
unsigned long dest_len;
|
unsigned long dest_len = 0;
|
||||||
bool compressed;
|
bool compressed;
|
||||||
|
|
||||||
/* DIRECTORY TABLE */
|
/* DIRECTORY TABLE */
|
||||||
|
@ -781,6 +788,8 @@ static int sqfs_read_directory_table(unsigned char **dir_table, u32 **pos_list)
|
||||||
dest_offset += dest_len;
|
dest_offset += dest_len;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dest_offset += dest_len;
|
||||||
} else {
|
} else {
|
||||||
memcpy(*dir_table + (j * SQFS_METADATA_BLOCK_SIZE),
|
memcpy(*dir_table + (j * SQFS_METADATA_BLOCK_SIZE),
|
||||||
src_table, src_len);
|
src_table, src_len);
|
||||||
|
@ -790,7 +799,6 @@ static int sqfs_read_directory_table(unsigned char **dir_table, u32 **pos_list)
|
||||||
* Offsets to the decompression destination, to the metadata
|
* Offsets to the decompression destination, to the metadata
|
||||||
* buffer 'dtb' and to the decompression source, respectively.
|
* buffer 'dtb' and to the decompression source, respectively.
|
||||||
*/
|
*/
|
||||||
dest_offset += dest_len;
|
|
||||||
table_offset += src_len + SQFS_HEADER_SIZE;
|
table_offset += src_len + SQFS_HEADER_SIZE;
|
||||||
src_table += src_len + SQFS_HEADER_SIZE;
|
src_table += src_len + SQFS_HEADER_SIZE;
|
||||||
}
|
}
|
||||||
|
@ -1138,6 +1146,9 @@ static int sqfs_get_regfile_info(struct squashfs_reg_inode *reg,
|
||||||
finfo->start = get_unaligned_le32(®->start_block);
|
finfo->start = get_unaligned_le32(®->start_block);
|
||||||
finfo->frag = SQFS_IS_FRAGMENTED(get_unaligned_le32(®->fragment));
|
finfo->frag = SQFS_IS_FRAGMENTED(get_unaligned_le32(®->fragment));
|
||||||
|
|
||||||
|
if (finfo->size < 1 || finfo->offset < 0 || finfo->start < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
if (finfo->frag) {
|
if (finfo->frag) {
|
||||||
datablk_count = finfo->size / le32_to_cpu(blksz);
|
datablk_count = finfo->size / le32_to_cpu(blksz);
|
||||||
ret = sqfs_frag_lookup(get_unaligned_le32(®->fragment),
|
ret = sqfs_frag_lookup(get_unaligned_le32(®->fragment),
|
||||||
|
@ -1145,6 +1156,8 @@ static int sqfs_get_regfile_info(struct squashfs_reg_inode *reg,
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
finfo->comp = true;
|
finfo->comp = true;
|
||||||
|
if (fentry->size < 1 || fentry->start < 0)
|
||||||
|
return -EINVAL;
|
||||||
} else {
|
} else {
|
||||||
datablk_count = DIV_ROUND_UP(finfo->size, le32_to_cpu(blksz));
|
datablk_count = DIV_ROUND_UP(finfo->size, le32_to_cpu(blksz));
|
||||||
}
|
}
|
||||||
|
@ -1168,6 +1181,9 @@ static int sqfs_get_lregfile_info(struct squashfs_lreg_inode *lreg,
|
||||||
finfo->start = get_unaligned_le64(&lreg->start_block);
|
finfo->start = get_unaligned_le64(&lreg->start_block);
|
||||||
finfo->frag = SQFS_IS_FRAGMENTED(get_unaligned_le32(&lreg->fragment));
|
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) {
|
if (finfo->frag) {
|
||||||
datablk_count = finfo->size / le32_to_cpu(blksz);
|
datablk_count = finfo->size / le32_to_cpu(blksz);
|
||||||
ret = sqfs_frag_lookup(get_unaligned_le32(&lreg->fragment),
|
ret = sqfs_frag_lookup(get_unaligned_le32(&lreg->fragment),
|
||||||
|
@ -1175,6 +1191,8 @@ static int sqfs_get_lregfile_info(struct squashfs_lreg_inode *lreg,
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
finfo->comp = true;
|
finfo->comp = true;
|
||||||
|
if (fentry->size < 1 || fentry->start < 0)
|
||||||
|
return -EINVAL;
|
||||||
} else {
|
} else {
|
||||||
datablk_count = DIV_ROUND_UP(finfo->size, le32_to_cpu(blksz));
|
datablk_count = DIV_ROUND_UP(finfo->size, le32_to_cpu(blksz));
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,9 @@ int sqfs_dir_offset(void *dir_i, u32 *m_list, int m_count)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (offset < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
for (j = 0; j < m_count; j++) {
|
for (j = 0; j < m_count; j++) {
|
||||||
if (m_list[j] == start_block)
|
if (m_list[j] == start_block)
|
||||||
return (++j * SQFS_METADATA_BLOCK_SIZE) + offset;
|
return (++j * SQFS_METADATA_BLOCK_SIZE) + offset;
|
||||||
|
|
|
@ -138,11 +138,14 @@ void *sqfs_find_inode(void *inode_table, int inode_number, __le32 inode_count,
|
||||||
int sqfs_read_metablock(unsigned char *file_mapping, int offset,
|
int sqfs_read_metablock(unsigned char *file_mapping, int offset,
|
||||||
bool *compressed, u32 *data_size)
|
bool *compressed, u32 *data_size)
|
||||||
{
|
{
|
||||||
unsigned char *data;
|
const unsigned char *data;
|
||||||
u16 header;
|
u16 header;
|
||||||
|
|
||||||
data = file_mapping + offset;
|
data = file_mapping + offset;
|
||||||
header = get_unaligned((u16 *)data);
|
header = get_unaligned((u16 *)data);
|
||||||
|
if (!header || !data)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
*compressed = SQFS_COMPRESSED_METADATA(header);
|
*compressed = SQFS_COMPRESSED_METADATA(header);
|
||||||
*data_size = SQFS_METADATA_SIZE(header);
|
*data_size = SQFS_METADATA_SIZE(header);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue