fs/squashfs: sqfs_read: fix memory leak on finfo.blk_sizes
authorRichard Genoud <richard.genoud@posteo.net>
Tue, 3 Nov 2020 11:11:18 +0000 (12:11 +0100)
committerMarek Szyprowski <m.szyprowski@samsung.com>
Mon, 15 Nov 2021 10:37:12 +0000 (11:37 +0100)
finfo.blk_sizes may not be freed in case of error in the for loop
Setting it to null and freeing it at the end makes prevents that from
happening.

Reviewed-by: Joao Marcos Costa <jmcosta944@gmail.com>
Signed-off-by: Richard Genoud <richard.genoud@posteo.net>
[jh80.chung: cherry picked from mainline commit 571b67ee1dcb989dc50575f14e87bfdef6bfd8db]
Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
Change-Id: I97086373caa5a031f3ba12aa4997de3eab10c530

fs/squashfs/sqfs.c

index f95d618..c816cd5 100644 (file)
@@ -1308,8 +1308,8 @@ static int sqfs_get_lregfile_info(struct squashfs_lreg_inode *lreg,
 int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
              loff_t *actread)
 {
-       char *dir, *fragment_block, *datablock = NULL, *data_buffer = NULL;
-       char *fragment, *file, *resolved, *data;
+       char *dir = NULL, *fragment_block, *datablock = NULL, *data_buffer = NULL;
+       char *fragment = NULL, *file = NULL, *resolved, *data;
        u64 start, n_blks, table_size, data_offset, table_offset;
        int ret, j, i_number, datablk_count = 0;
        struct squashfs_super_block *sblk = ctxt.sblk;
@@ -1334,7 +1334,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
        sqfs_split_path(&file, &dir, filename);
        ret = sqfs_opendir(dir, &dirsp);
        if (ret) {
-               goto free_paths;
+               goto out;
        }
 
        dirs = (struct squashfs_dir_stream *)dirsp;
@@ -1353,7 +1353,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
                printf("File not found.\n");
                *actread = 0;
                ret = -ENOENT;
-               goto free_paths;
+               goto out;
        }
 
        i_number = dirs->dir_header->inode_number + dirs->entry->inode_offset;
@@ -1368,7 +1368,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
                                                      sblk->block_size);
                if (datablk_count < 0) {
                        ret = -EINVAL;
-                       goto free_paths;
+                       goto out;
                }
 
                memcpy(finfo.blk_sizes, ipos + sizeof(*reg),
@@ -1381,7 +1381,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
                                                       sblk->block_size);
                if (datablk_count < 0) {
                        ret = -EINVAL;
-                       goto free_paths;
+                       goto out;
                }
 
                memcpy(finfo.blk_sizes, ipos + sizeof(*lreg),
@@ -1393,7 +1393,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
                resolved = sqfs_resolve_symlink(symlink, filename);
                ret = sqfs_read(resolved, buf, offset, len, actread);
                free(resolved);
-               goto free_paths;
+               goto out;
        case SQFS_BLKDEV_TYPE:
        case SQFS_CHRDEV_TYPE:
        case SQFS_LBLKDEV_TYPE:
@@ -1405,14 +1405,14 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
        default:
                printf("Unsupported entry type\n");
                ret = -EINVAL;
-               goto free_paths;
+               goto out;
        }
 
        /* If the user specifies a length, check its sanity */
        if (len) {
                if (len > finfo.size) {
                        ret = -EINVAL;
-                       goto free_paths;
+                       goto out;
                }
 
                finfo.size = len;
@@ -1423,7 +1423,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
                datablock = malloc(get_unaligned_le32(&sblk->block_size));
                if (!datablock) {
                        ret = -ENOMEM;
-                       goto free_paths;
+                       goto out;
                }
        }
 
@@ -1438,7 +1438,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
 
                if (!data_buffer) {
                        ret = -ENOMEM;
-                       goto free_datablk;
+                       goto out;
                }
 
                ret = sqfs_disk_read(start, n_blks, data_buffer);
@@ -1449,7 +1449,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
                         * image with mksquashfs's -b <block_size> option.
                         */
                        printf("Error: too many data blocks to be read.\n");
-                       goto free_buffer;
+                       goto out;
                }
 
                data = data_buffer + table_offset;
@@ -1460,7 +1460,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
                        ret = sqfs_decompress(&ctxt, datablock, &dest_len,
                                              data, table_size);
                        if (ret)
-                               goto free_buffer;
+                               goto out;
 
                        memcpy(buf + offset + *actread, datablock, dest_len);
                        *actread += dest_len;
@@ -1474,14 +1474,12 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
                data_buffer = NULL;
        }
 
-       free(finfo.blk_sizes);
-
        /*
         * There is no need to continue if the file is not fragmented.
         */
        if (!finfo.frag) {
                ret = 0;
-               goto free_buffer;
+               goto out;
        }
 
        start = frag_entry.start / ctxt.cur_dev->blksz;
@@ -1493,12 +1491,12 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
 
        if (!fragment) {
                ret = -ENOMEM;
-               goto free_buffer;
+               goto out;
        }
 
        ret = sqfs_disk_read(start, n_blks, fragment);
        if (ret < 0)
-               goto free_fragment;
+               goto out;
 
        /* File compressed and fragmented */
        if (finfo.frag && finfo.comp) {
@@ -1506,7 +1504,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
                fragment_block = malloc(dest_len);
                if (!fragment_block) {
                        ret = -ENOMEM;
-                       goto free_fragment;
+                       goto out;
                }
 
                ret = sqfs_decompress(&ctxt, fragment_block, &dest_len,
@@ -1514,7 +1512,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
                                      frag_entry.size);
                if (ret) {
                        free(fragment_block);
-                       goto free_fragment;
+                       goto out;
                }
 
                for (j = offset + *actread; j < finfo.size; j++) {
@@ -1533,17 +1531,15 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len,
                }
        }
 
-free_fragment:
+out:
        free(fragment);
-free_buffer:
-       if (datablk_count)
+       if (datablk_count) {
                free(data_buffer);
-free_datablk:
-       if (datablk_count)
                free(datablock);
-free_paths:
+       }
        free(file);
        free(dir);
+       free(finfo.blk_sizes);
        sqfs_closedir(dirsp);
 
        return ret;