Fix control flow issues and null pointer dereferences.

Signed-off-by: Joao Marcos Costa <jmcosta...@gmail.com>
---
 fs/squashfs/sqfs.c       | 20 +++++++++++++-------
 fs/squashfs/sqfs_dir.c   |  3 +--
 fs/squashfs/sqfs_inode.c |  5 ++++-
 3 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/fs/squashfs/sqfs.c b/fs/squashfs/sqfs.c
index f67f7c4a40..15208b4dab 100644
--- a/fs/squashfs/sqfs.c
+++ b/fs/squashfs/sqfs.c
@@ -154,7 +154,7 @@ static int sqfs_frag_lookup(u32 inode_fragment_index,
        header = get_unaligned_le16(metadata_buffer + table_offset);
        metadata = metadata_buffer + table_offset + SQFS_HEADER_SIZE;
 
-       if (!metadata) {
+       if (!metadata || !header) {
                ret = -ENOMEM;
                goto free_buffer;
        }
@@ -434,9 +434,9 @@ static int sqfs_search_dir(struct squashfs_dir_stream 
*dirs, char **token_list,
 {
        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;
+       struct squashfs_ldir_inode *ldir;
        struct squashfs_dir_inode *dir;
        struct fs_dir_stream *dirsp;
        struct fs_dirent *dent;
@@ -448,8 +448,8 @@ static int sqfs_search_dir(struct squashfs_dir_stream 
*dirs, char **token_list,
        table = sqfs_find_inode(dirs->inode_table, le32_to_cpu(sblk->inodes),
                                sblk->inodes, sblk->block_size);
 
-       /* root is a regular directory, not an extended one */
        dir = (struct squashfs_dir_inode *)table;
+       ldir = (struct squashfs_ldir_inode *)table;
 
        /* get directory offset in directory table */
        offset = sqfs_dir_offset(table, m_list, m_count);
@@ -1146,7 +1146,10 @@ static int sqfs_get_regfile_info(struct 
squashfs_reg_inode *reg,
        finfo->start = get_unaligned_le32(&reg->start_block);
        finfo->frag = SQFS_IS_FRAGMENTED(get_unaligned_le32(&reg->fragment));
 
-       if (finfo->size < 1 || finfo->offset < 0 || finfo->start < 0)
+       if (finfo->frag && finfo->offset == 0xFFFFFFFF)
+               return -EINVAL;
+
+       if (finfo->size < 1 || finfo->start == 0xFFFFFFFF)
                return -EINVAL;
 
        if (finfo->frag) {
@@ -1156,7 +1159,7 @@ static int sqfs_get_regfile_info(struct 
squashfs_reg_inode *reg,
                if (ret < 0)
                        return -EINVAL;
                finfo->comp = true;
-               if (fentry->size < 1 || fentry->start < 0)
+               if (fentry->size < 1 || fentry->start == 0x7FFFFFFF)
                        return -EINVAL;
        } else {
                datablk_count = DIV_ROUND_UP(finfo->size, le32_to_cpu(blksz));
@@ -1181,7 +1184,10 @@ static int sqfs_get_lregfile_info(struct 
squashfs_lreg_inode *lreg,
        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)
+       if (finfo->frag && finfo->offset == 0xFFFFFFFF)
+               return -EINVAL;
+
+       if (finfo->size < 1 || finfo->start == 0x7FFFFFFF)
                return -EINVAL;
 
        if (finfo->frag) {
@@ -1191,7 +1197,7 @@ static int sqfs_get_lregfile_info(struct 
squashfs_lreg_inode *lreg,
                if (ret < 0)
                        return -EINVAL;
                finfo->comp = true;
-               if (fentry->size < 1 || fentry->start < 0)
+               if (fentry->size < 1 || fentry->start == 0x7FFFFFFF)
                        return -EINVAL;
        } else {
                datablk_count = DIV_ROUND_UP(finfo->size, le32_to_cpu(blksz));
diff --git a/fs/squashfs/sqfs_dir.c b/fs/squashfs/sqfs_dir.c
index 00d2891e7d..a265b98fe6 100644
--- a/fs/squashfs/sqfs_dir.c
+++ b/fs/squashfs/sqfs_dir.c
@@ -34,8 +34,7 @@ int sqfs_dir_offset(void *dir_i, u32 *m_list, int m_count)
        struct squashfs_ldir_inode *ldir;
        struct squashfs_dir_inode *dir;
        u32 start_block;
-       u16 offset;
-       int j;
+       int j, offset;
 
        switch (get_unaligned_le16(&base->inode_type)) {
        case SQFS_DIR_TYPE:
diff --git a/fs/squashfs/sqfs_inode.c b/fs/squashfs/sqfs_inode.c
index 1387779a85..1368f3063c 100644
--- a/fs/squashfs/sqfs_inode.c
+++ b/fs/squashfs/sqfs_inode.c
@@ -142,8 +142,11 @@ int sqfs_read_metablock(unsigned char *file_mapping, int 
offset,
        u16 header;
 
        data = file_mapping + offset;
+       if (!data)
+               return -EFAULT;
+
        header = get_unaligned((u16 *)data);
-       if (!header || !data)
+       if (!header)
                return -EINVAL;
 
        *compressed = SQFS_COMPRESSED_METADATA(header);
-- 
2.17.1

Reply via email to