From 3b72612ad191cad29aad3982221ff3355bec798d Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Sat, 31 Oct 2020 09:07:50 +0800 Subject: [PATCH 1/4] fs: btrfs: volumes: prevent overflow for multiplying In __btrfs_map_block() we do a int * int and assign it to u64. This is not safe as the result (int * int) is still evaluated as (int) thus it can overflow. Convert one of the multiplier to u64 to prevent such problem. In real world, this should not cause problem as we have device number limit thus it won't go beyond 4G for a single stripe. But it's harder to teach coverity about all these hidden limits, so just fix the possible overflow. Reported-by: Coverity CID 312957 Reported-by: Coverity CID 312948 Signed-off-by: Qu Wenruo --- fs/btrfs/volumes.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index fcf52d4b0f..4aaaeab663 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1030,7 +1030,7 @@ again: */ stripe_nr = stripe_nr / map->stripe_len; - stripe_offset = stripe_nr * map->stripe_len; + stripe_offset = stripe_nr * (u64)map->stripe_len; BUG_ON(offset < stripe_offset); /* stripe_offset is the offset of this block in its stripe*/ @@ -1103,7 +1103,7 @@ again: rot = stripe_nr % map->num_stripes; /* Fill in the logical address of each stripe */ - tmp = stripe_nr * nr_data_stripes(map); + tmp = (u64)stripe_nr * nr_data_stripes(map); for (i = 0; i < nr_data_stripes(map); i++) raid_map[(i+rot) % map->num_stripes] = From 9dba07f14304612ed4ee6d827898aa0cb55d4e26 Mon Sep 17 00:00:00 2001 From: Campbell Suter Date: Mon, 23 Nov 2020 15:40:03 +1300 Subject: [PATCH 2/4] Fix squashfs failing to load sparse files SquashFS supports sprase blocks in files - that is, if a given block is composed only of zeros, it's not written to the output file to save space and it's on-disk length field is set to zero to indicate that. Previously the squashfs driver did not recognise that, and would attempt to read and decompress a zero-sized block, which obviously failed. The following command may be used to create a file for testing: cat <(dd if=/dev/urandom of=/dev/stdout bs=1M count=1) \ <(dd if=/dev/zero of=/dev/stdout bs=1M count=1) \ <(dd if=/dev/urandom of=/dev/stdout bs=1k count=200) >test_file Signed-off-by: Campbell Suter --- fs/squashfs/sqfs.c | 56 +++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/fs/squashfs/sqfs.c b/fs/squashfs/sqfs.c index 5de69ac3ca..dca13bd1f1 100644 --- a/fs/squashfs/sqfs.c +++ b/fs/squashfs/sqfs.c @@ -1310,7 +1310,7 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len, { 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; + u64 start, n_blks, table_size, data_offset, table_offset, sparse_size; int ret, j, i_number, datablk_count = 0; struct squashfs_super_block *sblk = ctxt.sblk; struct squashfs_fragment_block_entry frag_entry; @@ -1444,28 +1444,43 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len, n_blks = DIV_ROUND_UP(table_size + table_offset, ctxt.cur_dev->blksz); - data_buffer = malloc_cache_aligned(n_blks * ctxt.cur_dev->blksz); + /* Don't load any data for sparse blocks */ + if (finfo.blk_sizes[j] == 0) { + n_blks = 0; + table_offset = 0; + data_buffer = NULL; + data = NULL; + } else { + data_buffer = malloc_cache_aligned(n_blks * ctxt.cur_dev->blksz); - if (!data_buffer) { - ret = -ENOMEM; - goto out; + if (!data_buffer) { + ret = -ENOMEM; + goto out; + } + + ret = sqfs_disk_read(start, n_blks, data_buffer); + if (ret < 0) { + /* + * Possible causes: too many data blocks or too large + * SquashFS block size. Tip: re-compile the SquashFS + * image with mksquashfs's -b option. + */ + printf("Error: too many data blocks to be read.\n"); + goto out; + } + + data = data_buffer + table_offset; } - ret = sqfs_disk_read(start, n_blks, data_buffer); - if (ret < 0) { - /* - * Possible causes: too many data blocks or too large - * SquashFS block size. Tip: re-compile the SquashFS - * image with mksquashfs's -b option. - */ - printf("Error: too many data blocks to be read.\n"); - goto out; - } - - data = data_buffer + table_offset; - /* Load the data */ - if (SQFS_COMPRESSED_BLOCK(finfo.blk_sizes[j])) { + if (finfo.blk_sizes[j] == 0) { + /* This is a sparse block */ + sparse_size = get_unaligned_le32(&sblk->block_size); + if ((*actread + sparse_size) > len) + sparse_size = len - *actread; + memset(buf + *actread, 0, sparse_size); + *actread += sparse_size; + } else if (SQFS_COMPRESSED_BLOCK(finfo.blk_sizes[j])) { dest_len = get_unaligned_le32(&sblk->block_size); ret = sqfs_decompress(&ctxt, datablock, &dest_len, data, table_size); @@ -1484,7 +1499,8 @@ int sqfs_read(const char *filename, void *buf, loff_t offset, loff_t len, } data_offset += table_size; - free(data_buffer); + if (data_buffer) + free(data_buffer); data_buffer = NULL; if (*actread >= len) break; From 3b00a6bafc726a9a9df45346fb734d9ecef7b428 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 25 Dec 2020 13:45:25 +0100 Subject: [PATCH 3/4] fs: btrfs: simplify close_ctree_fs_info() At the beginning of close_ctree_fs_info() the value 0 is assigned to err and never changed before testing it. Let's get rid of the superfluous variable. Fixes: f06bfcf54d0e ("fs: btrfs: Crossport open_ctree_fs_info() from btrfs-progs") Signed-off-by: Heinrich Schuchardt Reviewed-by: Qu Wenruo --- fs/btrfs/disk-io.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 01e7cee520..b332ecb796 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1030,7 +1030,6 @@ out: int close_ctree_fs_info(struct btrfs_fs_info *fs_info) { int ret; - int err = 0; free_fs_roots_tree(&fs_info->fs_root_tree); @@ -1038,9 +1037,7 @@ int close_ctree_fs_info(struct btrfs_fs_info *fs_info) ret = btrfs_close_devices(fs_info->fs_devices); btrfs_cleanup_all_caches(fs_info); btrfs_free_fs_info(fs_info); - if (!err) - err = ret; - return err; + return ret; } int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid) From 81f562719e475b0e13ff7a0201cae19f8cc367fe Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 25 Dec 2020 15:19:39 +0100 Subject: [PATCH 4/4] ubifs: do not decide upon uninitialized variable Before 'if (err)' we have to initialize the variable otherwise we use a random value from the stack. Signed-off-by: Heinrich Schuchardt --- fs/ubifs/io.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index eb14b89544..9962cbe7eb 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c @@ -114,7 +114,7 @@ int ubifs_leb_read(const struct ubifs_info *c, int lnum, void *buf, int offs, int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs, int len) { - int err; + int err = 0; ubifs_assert(!c->ro_media && !c->ro_mount); if (c->ro_error) @@ -136,7 +136,7 @@ int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs, int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len) { - int err; + int err = 0; ubifs_assert(!c->ro_media && !c->ro_mount); if (c->ro_error) @@ -158,7 +158,7 @@ int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len) int ubifs_leb_unmap(struct ubifs_info *c, int lnum) { - int err; + int err = 0; ubifs_assert(!c->ro_media && !c->ro_mount); if (c->ro_error) @@ -179,7 +179,7 @@ int ubifs_leb_unmap(struct ubifs_info *c, int lnum) int ubifs_leb_map(struct ubifs_info *c, int lnum) { - int err; + int err = 0; ubifs_assert(!c->ro_media && !c->ro_mount); if (c->ro_error)