summaryrefslogtreecommitdiff
path: root/btrfs-image.c
diff options
context:
space:
mode:
authorZach Brown <zab@redhat.com>2013-10-07 14:42:57 -0700
committerChris Mason <chris.mason@fusionio.com>2013-10-16 08:23:13 -0400
commit69dc09a3ce7e914111c1cf9da93021d9b5d51762 (patch)
tree43561af432b0fedc0a30b32524839771cd9b2af5 /btrfs-image.c
parent961eaa7d3975928635e3dc775e6ab3a2f36a5303 (diff)
btrfs-progs: don't overflow read buffer in image
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 <zab@redhat.com> Signed-off-by: David Sterba <dsterba@suse.cz> Signed-off-by: Chris Mason <chris.mason@fusionio.com>
Diffstat (limited to 'btrfs-image.c')
-rw-r--r--btrfs-image.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/btrfs-image.c b/btrfs-image.c
index 52209a76..c316a642 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);