app: aboot: Verify the boot.img address are not overlapping with LK address.
CRs-Fixed: 491421
Change-Id: Iae544722dab4eea3ba5d7b7721ea72d3a4edbe18
diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c
index 48724d0..1fe24a8 100644
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -85,6 +85,12 @@
#define EMMC_BOOT_IMG_HEADER_ADDR 0xFF000
#endif
+#ifndef MEMSIZE
+#define MEMSIZE 1024*1024
+#endif
+
+#define MAX_TAGS_SIZE 1024
+
#define RECOVERY_MODE 0x77665502
#define FASTBOOT_MODE 0x77665500
@@ -501,6 +507,26 @@
entry(0, machtype, (unsigned*)tags_phys);
}
+/* Function to check if the memory address range falls within the aboot
+ * boundaries.
+ * start: Start of the memory region
+ * size: Size of the memory region
+ */
+int check_aboot_addr_range_overlap(uint32_t start, uint32_t size)
+{
+ /* Check for boundary conditions. */
+ if ((start + size) < start)
+ return -1;
+
+ /* Check for memory overlap. */
+ if ((start < MEMBASE) && ((start + size) <= MEMBASE))
+ return 0;
+ else if (start > (MEMBASE + MEMSIZE))
+ return 0;
+ else
+ return -1;
+}
+
#define ROUND_TO_PAGE(x,y) (((x) + (y)) & (~(y)))
BUF_DMA_ALIGN(buf, 4096); //Equal to max-supported pagesize
@@ -508,6 +534,45 @@
BUF_DMA_ALIGN(dt_buf, 4096);
#endif
+static void verify_signed_bootimg(uint32_t bootimg_addr, uint32_t bootimg_size)
+{
+ int ret;
+
+ /* Assume device is rooted at this time. */
+ device.is_tampered = 1;
+
+ dprintf(INFO, "Authenticating boot image (%d): start\n", bootimg_size);
+
+ ret = image_verify((unsigned char *)bootimg_addr,
+ (unsigned char *)(bootimg_addr + bootimg_size),
+ bootimg_size,
+ CRYPTO_AUTH_ALG_SHA256);
+
+ dprintf(INFO, "Authenticating boot image: done return value = %d\n", ret);
+
+ if (ret)
+ {
+ /* Authorized kernel */
+ device.is_tampered = 0;
+ }
+
+#if USE_PCOM_SECBOOT
+ set_tamper_flag(device.is_tampered);
+#endif
+
+ if(device.is_tampered)
+ {
+ write_device_info_mmc(&device);
+ #ifdef TZ_TAMPER_FUSE
+ set_tamper_fuse_cmd();
+ #endif
+ #ifdef ASSERT_ON_TAMPER
+ dprintf(CRITICAL, "Device is tampered. Asserting..\n");
+ ASSERT(0);
+ #endif
+ }
+}
+
int boot_linux_from_mmc(void)
{
struct boot_img_hdr *hdr = (void*) buf;
@@ -589,22 +654,46 @@
hdr->kernel_addr = VA((addr_t)(hdr->kernel_addr));
hdr->ramdisk_addr = VA((addr_t)(hdr->ramdisk_addr));
hdr->tags_addr = VA((addr_t)(hdr->tags_addr));
+
+ kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
+ ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
+
+ /* Check if the addresses in the header are valid. */
+ if (check_aboot_addr_range_overlap(hdr->kernel_addr, kernel_actual) ||
+ check_aboot_addr_range_overlap(hdr->ramdisk_addr, ramdisk_actual))
+ {
+ dprintf(CRITICAL, "kernel/ramdisk addresses overlap with aboot addresses.\n");
+ return -1;
+ }
+
+#ifndef DEVICE_TREE
+ if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
+ {
+ dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
+ return -1;
+ }
+#endif
+
/* Authenticate Kernel */
if(target_use_signed_kernel() && (!device.is_unlocked) && (!device.is_tampered))
{
+ offset = 0;
+
image_addr = (unsigned char *)target_get_scratch_address();
- kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
- ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
+
#if DEVICE_TREE
dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
imagesize_actual = (page_size + kernel_actual + ramdisk_actual + dt_actual);
+
+ if (check_aboot_addr_range_overlap(hdr->tags_addr, hdr->dt_size))
+ {
+ dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
+ return -1;
+ }
#else
imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
-#endif
- offset = 0;
- /* Assuming device rooted at this time */
- device.is_tampered = 1;
+#endif
dprintf(INFO, "Loading boot image (%d): start\n", imagesize_actual);
bs_set_timestamp(BS_KERNEL_LOAD_START);
@@ -624,31 +713,14 @@
if(mmc_read(ptn + offset, (void *)(image_addr + offset), page_size))
{
dprintf(CRITICAL, "ERROR: Cannot read boot image signature\n");
+ return -1;
}
- else
- {
- dprintf(INFO, "Authenticating boot image (%d): start\n", imagesize_actual);
- auth_kernel_img = image_verify((unsigned char *)image_addr,
- (unsigned char *)(image_addr + imagesize_actual),
- imagesize_actual,
- CRYPTO_AUTH_ALG_SHA256);
-
- dprintf(INFO, "Authenticating boot image (%d): done\n", imagesize_actual);
-
- if(auth_kernel_img)
- {
- /* Authorized kernel */
- device.is_tampered = 0;
- }
- }
+ verify_signed_bootimg(image_addr, imagesize_actual);
/* Move kernel, ramdisk and device tree to correct address */
memmove((void*) hdr->kernel_addr, (char *)(image_addr + page_size), hdr->kernel_size);
memmove((void*) hdr->ramdisk_addr, (char *)(image_addr + page_size + kernel_actual), hdr->ramdisk_size);
-#if DEVICE_TREE
- memmove((void*) hdr->tags_addr, (char *)(image_addr + page_size + kernel_actual + ramdisk_actual), hdr->dt_size);
-#endif
#if DEVICE_TREE
if(hdr->dt_size) {
@@ -672,7 +744,13 @@
return -1;
}
- /* Read device device tree in the "tags_add */
+ /* Validate and Read device device tree in the "tags_add */
+ if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry_ptr->size))
+ {
+ dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
+ return -1;
+ }
+
memmove((void *)hdr->tags_addr, (char *)dt_table_offset + dt_entry_ptr->offset, dt_entry_ptr->size);
} else {
/*
@@ -689,22 +767,9 @@
}
}
#endif
- /* Make sure everything from scratch address is read before next step!*/
- if(device.is_tampered)
- {
- write_device_info_mmc(&device);
- #ifdef TZ_TAMPER_FUSE
- set_tamper_fuse_cmd();
- #endif
- }
- #if USE_PCOM_SECBOOT
- set_tamper_flag(device.is_tampered);
- #endif
}
else
{
- kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
- ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
second_actual = ROUND_TO_PAGE(hdr->second_size, page_mask);
dprintf(INFO, "Loading boot image (%d): start\n",
@@ -765,7 +830,13 @@
return -1;
}
- /* Read device device tree in the "tags_add */
+ /* Validate and Read device device tree in the "tags_add */
+ if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry_ptr->size))
+ {
+ dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
+ return -1;
+ }
+
if(mmc_read(ptn + offset + dt_entry_ptr->offset,
(void *)hdr->tags_addr, dt_entry_ptr->size)) {
dprintf(CRITICAL, "ERROR: Cannot read device tree\n");
@@ -872,26 +943,47 @@
update_ker_tags_rdisk_addr(hdr);
/* Get virtual addresses since the hdr saves physical addresses. */
- hdr->kernel_addr = VA(hdr->kernel_addr);
- hdr->ramdisk_addr = VA(hdr->ramdisk_addr);
- hdr->tags_addr = VA(hdr->tags_addr);
+ hdr->kernel_addr = VA((addr_t)(hdr->kernel_addr));
+ hdr->ramdisk_addr = VA((addr_t)(hdr->ramdisk_addr));
+ hdr->tags_addr = VA((addr_t)(hdr->tags_addr));
+
+ kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
+ ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
+
+ /* Check if the addresses in the header are valid. */
+ if (check_aboot_addr_range_overlap(hdr->kernel_addr, kernel_actual) ||
+ check_aboot_addr_range_overlap(hdr->ramdisk_addr, ramdisk_actual))
+ {
+ dprintf(CRITICAL, "kernel/ramdisk addresses overlap with aboot addresses.\n");
+ return -1;
+ }
+
+#ifndef DEVICE_TREE
+ if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
+ {
+ dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
+ return -1;
+ }
+#endif
/* Authenticate Kernel */
if(target_use_signed_kernel() && (!device.is_unlocked) && (!device.is_tampered))
{
image_addr = (unsigned char *)target_get_scratch_address();
- kernel_actual = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
- ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
+ offset = 0;
+
#if DEVICE_TREE
dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
imagesize_actual = (page_size + kernel_actual + ramdisk_actual + dt_actual);
+
+ if (check_aboot_addr_range_overlap(hdr->tags_addr, hdr->dt_size))
+ {
+ dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
+ return -1;
+ }
#else
imagesize_actual = (page_size + kernel_actual + ramdisk_actual);
#endif
- offset = 0;
-
- /* Assuming device rooted at this time */
- device.is_tampered = 1;
dprintf(INFO, "Loading boot image (%d): start\n", imagesize_actual);
bs_set_timestamp(BS_KERNEL_LOAD_START);
@@ -911,30 +1003,22 @@
if (flash_read(ptn, offset, (void *)(image_addr + offset), page_size))
{
dprintf(CRITICAL, "ERROR: Cannot read boot image signature\n");
+ return -1;
}
- else
- {
- dprintf(INFO, "Authenticating boot image (%d): start\n", imagesize_actual);
- /* Verify signature */
- auth_kernel_img = image_verify((unsigned char *)image_addr,
- (unsigned char *)(image_addr + imagesize_actual),
- imagesize_actual,
- CRYPTO_AUTH_ALG_SHA256);
-
- dprintf(INFO, "Authenticating boot image (%d): done\n", imagesize_actual);
-
- if(auth_kernel_img)
- {
- /* Authorized kernel */
- device.is_tampered = 0;
- }
- }
+ verify_signed_bootimg(image_addr, imagesize_actual);
/* Move kernel and ramdisk to correct address */
memmove((void*) hdr->kernel_addr, (char *)(image_addr + page_size), hdr->kernel_size);
memmove((void*) hdr->ramdisk_addr, (char *)(image_addr + page_size + kernel_actual), hdr->ramdisk_size);
#if DEVICE_TREE
+ /* Validate and Read device device tree in the "tags_add */
+ if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry_ptr->size))
+ {
+ dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
+ return -1;
+ }
+
memmove((void*) hdr->tags_addr, (char *)(image_addr + page_size + kernel_actual + ramdisk_actual), hdr->dt_size);
#endif
@@ -1007,6 +1091,13 @@
return -1;
}
+ /* Validate and Read device device tree in the "tags_add */
+ if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry_ptr->size))
+ {
+ dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
+ return -1;
+ }
+
/* Read device device tree in the "tags_add */
if(flash_read(ptn, offset + dt_entry_ptr->offset,
(void *)hdr->tags_addr, dt_entry_ptr->size)) {
@@ -1235,6 +1326,13 @@
return -1;
}
+ /* Validate and Read device device tree in the "tags_add */
+ if (check_aboot_addr_range_overlap(hdr->tags_addr, dt_entry_ptr->size))
+ {
+ dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
+ return -1;
+ }
+
/* Read device device tree in the "tags_add */
memmove((void*) hdr->tags_addr,
boot_image_start + dt_image_offset + dt_entry_ptr->offset,
@@ -1286,6 +1384,14 @@
hdr->ramdisk_addr = VA(hdr->ramdisk_addr);
hdr->tags_addr = VA(hdr->tags_addr);
+ /* Check if the addresses in the header are valid. */
+ if (check_aboot_addr_range_overlap(hdr->kernel_addr, kernel_actual) ||
+ check_aboot_addr_range_overlap(hdr->ramdisk_addr, ramdisk_actual))
+ {
+ dprintf(CRITICAL, "kernel/ramdisk addresses overlap with aboot addresses.\n");
+ return -1;
+ }
+
/* sz should have atleast raw boot image */
if (page_size + kernel_actual + ramdisk_actual > sz) {
fastboot_fail("incomplete bootimage");
@@ -1297,6 +1403,12 @@
ret = copy_dtb(data);
dtb_copied = !ret ? 1 : 0;
+#else
+ if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
+ {
+ dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
+ return -1;
+ }
#endif
/* Load ramdisk & kernel */
@@ -1320,6 +1432,14 @@
}
#endif
+#ifndef DEVICE_TREE
+ if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
+ {
+ dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
+ return -1;
+ }
+#endif
+
fastboot_okay("");
udc_stop();
@@ -1831,6 +1951,8 @@
page_mask = page_size - 1;
}
+ ASSERT((MEMBASE + MEMSIZE) > MEMBASE);
+
if(target_use_signed_kernel())
{
read_device_info(&device);