|
From: | tielei wang |
Subject: | [Qemu-devel] multi potential integer overflow vulnerabilities |
Date: | Mon, 25 Aug 2008 19:09:28 +0800 |
Hi,
I think there are multi- potential integer overflow vulnerabilities in QEMU
The 1st one, boch_open() function in block-boch.c
diff -U 25
block-bochs.c block-bochs_patched.c
--- block-bochs.c 2008-01-07
03:38:41.000000000 +0800
+++ block-bochs_patched.c 2008-08-25
09:46:59.000000000 +0800
@@ -126,50 +126,52 @@
s->fd = fd;
if (read(fd, &bochs, sizeof(bochs)) != sizeof(bochs)) {
goto
fail;
}
// .......
lseek(s->fd, le32_to_cpu(bochs.header),
SEEK_SET);
s->catalog_size =
le32_to_cpu(bochs.extra.redolog.catalog);
+ if(s->catalog_size >
MAX/4)
+ goto fail;
s->catalog_bitmap =
qemu_malloc(s->catalog_size * 4);
boch_open() reads some datas from "fd" to "bochs", so "bochs.extra.redolog.catalog" is a tainted value. s->catalog_size * 4 is a potential integer overflow operation, results in s->catalog_bitmap is allocated with a small memory region.
The 2nd one, cloop_open() function in block-cloop.c
diff -U 6
block-cloop.c block-cloop_pathched.c
--- block-cloop.c 2008-01-07
03:38:41.000000000 +0800
+++ block-cloop_pathched.c 2008-08-25
10:01:23.000000000 +0800
@@ -72,12 +72,17 @@
if(read(s->fd,&s->n_blocks,4)<4)
goto
cloop_close;
s->n_blocks=be32_to_cpu(s->n_blocks);
/*
read offsets */
offsets_size=s->n_blocks*sizeof(uint64_t);
+ if
(s->n_blocks > MAX/ sizeof(uint64_t)){
+
close(s->fd);
+ return -1;
+ }
+
if(!(s->offsets=(uint64_t*)malloc(offsets_size))
s->n_blocks is a tainted data from file, so "offsets_size=s->n_blocks*sizeof(uint64_t) " is a potential integer overflow operation. offsets_size is smaller than the value it should be.
The 3rd one, parallels_open() function in block- parallels.c
diff -U 16
block-parallels.c block-parallels_patched.c
--- block-parallels.c
2008-01-07 03:38:41.000000000 +0800
+++ block-parallels_patched.c
2008-08-25 10:10:35.000000000 +0800
@@ -87,32 +87,34 @@
if (read(fd,
&ph, sizeof(ph)) != sizeof(ph))
goto fail;
//……
s->tracks
= le32_to_cpu(ph.tracks);
s->catalog_size =
le32_to_cpu(ph.catalog_entries);
+ if(s->catalog_size >
MAX/4)
+ goto fail;
s->catalog_bitmap
= qemu_malloc(s->catalog_size * 4);
Similar with the 1st one, ph.catalog_entries is a tainted data. We can't use it as malloc function's parameter.
The 4th one, qcow_open() function in block-qcow.c
if
(bdrv_pread(s->hd, 0, &header, sizeof(header)) !=
sizeof(header))
goto fail;
//......
s->cluster_bits =
header.cluster_bits;
s->cluster_size = 1 <<
s->cluster_bits;
s->cluster_sectors = 1 <<
(s->cluster_bits - 9);
s->l2_bits = header.l2_bits;
s->l2_size = 1 << s->l2_bits;
bs->total_sectors =
header.size / 512;
s->cluster_offset_mask = (1LL << (63 -
s->cluster_bits)) - 1;
/* read the
level 1 table */
shift = s->cluster_bits + s->l2_bits;
s->l1_size = (header.size + (1LL << shift) - 1) >>
shift;
s->l1_table_offset = header.l1_table_offset;
s->l1_table =
qemu_malloc(s->l1_size * sizeof(uint64_t));
A crafted file could cause s->l1_size big enough so that "s->l1_size * sizeof(uint64_t)" is an integer overflow operation.
By the way, qcow_open() function has other similar problems.
The 5th one, vmdk_open() function in block-vmdk.c
VMDK4Header header;
if (read(fd, &header, sizeof(header)) != sizeof(header))
goto fail;
s->size = le32_to_cpu(header.capacity);
prv->cluster_sectors = le32_to_cpu(header.granularity);
prv->l2_size = le32_to_cpu(header.num_gtes_per_gte);
prv->l1_entry_sectors = prv->l2_size * prv->cluster_sectors;
if (prv->l1_entry_sectors <= 0)
goto fail;
prv->l1_size = (s->size + prv->l1_entry_sectors - 1)
/ prv->l1_entry_sectors;
prv->l1_table_offset = le64_to_cpu(header.rgd_offset) << 9;
prv->l1_backup_table_offset =
le64_to_cpu(header.gd_offset) << 9;
} else {
goto fail;
}
/* read the L1 table */
+ if(prv->l1_size > INT_MAX/sizeof(uint32_t))
+ goto fail;
l1_size = prv->l1_size * sizeof(uint32_t);
prv->l1_table = malloc(l1_size);
If header.capacity is very huge, but both header.granularity and header.num_gtes_per_gte are 1, then
prv->l1_size = (s->size +prv->l1_entry_sectors - 1)/ prv->l1_entry_sectors = s->size = header.capacity.
Now, prv->l1_size * sizeof(uint32_t) is an integer overflow operation.
The 6th one, vpc_open() function in block-vpc.c
if (read(fd, &header, HEADER_SIZE) != HEADER_SIZE)
goto
fail;
//......
s->pagetable_entries =
be32_to_cpu(header.type.sparse.pagetable_entries);
s->pagetable =
qemu_malloc(s->pagetable_entries * 4);
header.type.sparse.pagetable_entries is a tainted value, so it shouldn't be used as malloc's parameter directlty after multiplication operation.
Waiting for your reply, thanks!
(I sent a mail before this one, but the mail didn't appear in the mail list)
Wangtielei
[Prev in Thread] | Current Thread | [Next in Thread] |