Merge "app: aboot: check for buffer over reads"
diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c
index 83d1531..3daaef5 100644
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -2263,6 +2263,8 @@
int index = INVALID_PTN;
uint32_t i;
uint8_t lun = 0;
+ /*End of the sparse image address*/
+ uint32_t data_end = (uint32_t)data + sz;
index = partition_get_index(arg);
ptn = partition_get_offset(index);
@@ -2272,28 +2274,34 @@
}
size = partition_get_size(index);
- if (ROUND_TO_PAGE(sz,511) > size) {
- fastboot_fail("size too large");
- return;
- }
lun = partition_get_lun(index);
mmc_set_lun(lun);
+ if (sz < sizeof(sparse_header_t)) {
+ fastboot_fail("size too low");
+ return;
+ }
+
/* Read and skip over sparse image header */
sparse_header = (sparse_header_t *) data;
+
if (((uint64_t)sparse_header->total_blks * (uint64_t)sparse_header->blk_sz) > size) {
fastboot_fail("size too large");
return;
}
- data += sparse_header->file_hdr_sz;
- if(sparse_header->file_hdr_sz > sizeof(sparse_header_t))
+ data += sizeof(sparse_header_t);
+
+ if (data_end < (uint32_t)data) {
+ fastboot_fail("buffer overreads occured due to invalid sparse header");
+ return;
+ }
+
+ if(sparse_header->file_hdr_sz != sizeof(sparse_header_t))
{
- /* Skip the remaining bytes in a header that is longer than
- * we expected.
- */
- data += (sparse_header->file_hdr_sz - sizeof(sparse_header_t));
+ fastboot_fail("sparse header size mismatch");
+ return;
}
dprintf (SPEW, "=== Sparse Image Header ===\n");
@@ -2318,17 +2326,20 @@
chunk_header = (chunk_header_t *) data;
data += sizeof(chunk_header_t);
+ if (data_end < (uint32_t)data) {
+ fastboot_fail("buffer overreads occured due to invalid sparse header");
+ return;
+ }
+
dprintf (SPEW, "=== Chunk Header ===\n");
dprintf (SPEW, "chunk_type: 0x%x\n", chunk_header->chunk_type);
dprintf (SPEW, "chunk_data_sz: 0x%x\n", chunk_header->chunk_sz);
dprintf (SPEW, "total_size: 0x%x\n", chunk_header->total_sz);
- if(sparse_header->chunk_hdr_sz > sizeof(chunk_header_t))
+ if(sparse_header->chunk_hdr_sz != sizeof(chunk_header_t))
{
- /* Skip the remaining bytes in a header that is longer than
- * we expected.
- */
- data += (sparse_header->chunk_hdr_sz - sizeof(chunk_header_t));
+ fastboot_fail("chunk header size mismatch");
+ return;
}
chunk_data_sz = sparse_header->blk_sz * chunk_header->chunk_sz;
@@ -2359,6 +2370,11 @@
return;
}
+ if (data_end < (uint32_t)data + chunk_data_sz) {
+ fastboot_fail("buffer overreads occured due to invalid sparse header");
+ return;
+ }
+
if(mmc_write(ptn + ((uint64_t)total_blocks*sparse_header->blk_sz),
chunk_data_sz,
(unsigned int*)data))
@@ -2389,6 +2405,10 @@
return;
}
+ if (data_end < (uint32_t)data + sizeof(uint32_t)) {
+ fastboot_fail("buffer overreads occured due to invalid sparse header");
+ return;
+ }
fill_val = *(uint32_t *)data;
data = (char *) data + sizeof(uint32_t);
chunk_blk_cnt = chunk_data_sz / sparse_header->blk_sz;
@@ -2441,7 +2461,15 @@
return;
}
total_blocks += chunk_header->chunk_sz;
+ if ((uint32_t)data > UINT_MAX - chunk_data_sz) {
+ fastboot_fail("integer overflow occured");
+ return;
+ }
data += chunk_data_sz;
+ if (data_end < (uint32_t)data) {
+ fastboot_fail("buffer overreads occured due to invalid sparse header");
+ return;
+ }
break;
default: