search_for_chunk_blocks() allocates a fixed-size buffer and then reads arbitrary u32 sized buffers in to it. Instead let's fail if the item is bigger than the buffer. This was found by static analysis.
Signed-off-by: Zach Brown <[email protected]> --- btrfs-image.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/btrfs-image.c b/btrfs-image.c index 7474642..03ad4e9 100644 --- a/btrfs-image.c +++ b/btrfs-image.c @@ -2011,6 +2011,7 @@ static int search_for_chunk_blocks(struct mdrestore_struct *mdres, u64 current_cluster = cluster_bytenr, bytenr; u64 item_bytenr; u32 bufsize, nritems, i; + u32 max_size = MAX_PENDING_SIZE * 2; u8 *buffer, *tmp = NULL; int ret = 0; @@ -2020,7 +2021,7 @@ static int search_for_chunk_blocks(struct mdrestore_struct *mdres, return -ENOMEM; } - buffer = malloc(MAX_PENDING_SIZE * 2); + buffer = malloc(max_size); if (!buffer) { fprintf(stderr, "Error allocing buffer\n"); free(cluster); @@ -2028,7 +2029,7 @@ static int search_for_chunk_blocks(struct mdrestore_struct *mdres, } if (mdres->compress_method == COMPRESS_ZLIB) { - tmp = malloc(MAX_PENDING_SIZE * 2); + tmp = malloc(max_size); if (!tmp) { fprintf(stderr, "Error allocing tmp buffer\n"); free(cluster); @@ -2079,6 +2080,13 @@ static int search_for_chunk_blocks(struct mdrestore_struct *mdres, bufsize = le32_to_cpu(item->size); item_bytenr = le64_to_cpu(item->bytenr); + if (bufsize > max_size) { + fprintf(stderr, "item %u size %u too big\n", + i, bufsize); + ret = -EIO; + break; + } + if (mdres->compress_method == COMPRESS_ZLIB) { ret = fread(tmp, bufsize, 1, mdres->in); if (ret != 1) { @@ -2088,7 +2096,7 @@ static int search_for_chunk_blocks(struct mdrestore_struct *mdres, break; } - size = MAX_PENDING_SIZE * 2; + size = max_size; ret = uncompress(buffer, (unsigned long *)&size, tmp, bufsize); -- 1.7.11.7 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
