app: aboot: check for integer overflow during sparse image flash.
Add integer overflow checks for the total blocks during the
sparse image flash.
Change-Id: Ib7b8809cdb45855c6e45a235e9a39e29d3eebe4e
diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c
index 5451150..3578c6d 100644
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -2123,6 +2123,11 @@
/* Start processing chunks */
for (chunk=0; chunk<sparse_header->total_chunks; chunk++)
{
+ /* Make sure the total image size does not exceed the partition size */
+ if(((uint64_t)total_blocks * (uint64_t)sparse_header->blk_sz) >= size) {
+ fastboot_fail("size too large");
+ return;
+ }
/* Read and skip over chunk header */
chunk_header = (chunk_header_t *) data;
data += sizeof(chunk_header_t);
@@ -2141,6 +2146,23 @@
}
chunk_data_sz = sparse_header->blk_sz * chunk_header->chunk_sz;
+
+ /* Make sure multiplication does not overflow uint32 size */
+ if (sparse_header->blk_sz && (chunk_header->chunk_sz != chunk_data_sz / sparse_header->blk_sz))
+ {
+ fastboot_fail("Bogus size sparse and chunk header");
+ return;
+ }
+
+ /* Make sure that the chunk size calculated from sparse image does not
+ * exceed partition size
+ */
+ if ((uint64_t)total_blocks * (uint64_t)sparse_header->blk_sz + chunk_data_sz > size)
+ {
+ fastboot_fail("Chunk data size exceeds partition size");
+ return;
+ }
+
switch (chunk_header->chunk_type)
{
case CHUNK_TYPE_RAW:
@@ -2158,6 +2180,10 @@
fastboot_fail("flash write failure");
return;
}
+ if(total_blocks > (UINT_MAX - chunk_header->chunk_sz)) {
+ fastboot_fail("Bogus size for RAW chunk type");
+ return;
+ }
total_blocks += chunk_header->chunk_sz;
data += chunk_data_sz;
break;
@@ -2188,6 +2214,13 @@
for (i = 0; i < chunk_blk_cnt; i++)
{
+ /* Make sure that the data written to partition does not exceed partition size */
+ if ((uint64_t)total_blocks * (uint64_t)sparse_header->blk_sz + sparse_header->blk_sz > size)
+ {
+ fastboot_fail("Chunk data size for fill type exceeds partition size");
+ return;
+ }
+
if(mmc_write(ptn + ((uint64_t)total_blocks*sparse_header->blk_sz),
sparse_header->blk_sz,
fill_buf))
@@ -2204,6 +2237,10 @@
break;
case CHUNK_TYPE_DONT_CARE:
+ if(total_blocks > (UINT_MAX - chunk_header->chunk_sz)) {
+ fastboot_fail("bogus size for chunk DONT CARE type");
+ return;
+ }
total_blocks += chunk_header->chunk_sz;
break;
@@ -2213,6 +2250,10 @@
fastboot_fail("Bogus chunk size for chunk type Dont Care");
return;
}
+ if(total_blocks > (UINT_MAX - chunk_header->chunk_sz)) {
+ fastboot_fail("bogus size for chunk CRC type");
+ return;
+ }
total_blocks += chunk_header->chunk_sz;
data += chunk_data_sz;
break;