loader: add checking of reset address
In a multi image context it is possible for a user to upload an image
to the wrong secondary slot. As the same key is used for both images
MCUboot will overwrite image 0 with a variant of image 1.
If direct overwrite is enabled it is not trivial to recover from this.
To mitigate this issue we introduce a check of the reset address within
the vector table.
If the reset address in the new image is not contained within the
primary slot the image is deemed incorrect and is deleted from the
secondary slot
Signed-off-by: Håkon Øye Amundsen <haakon.amundsen@nordicsemi.no>
diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c
index af4d12e..a26159c 100644
--- a/boot/bootutil/src/loader.c
+++ b/boot/bootutil/src/loader.c
@@ -773,6 +773,41 @@
goto out;
}
+#if MCUBOOT_IMAGE_NUMBER > 1 && !defined(MCUBOOT_ENC_IMAGES) && defined(MCUBOOT_VERIFY_IMG_ADDRESS)
+ /* Verify that the image in the secondary slot has a reset address
+ * located in the primary slot. This is done to avoid users incorrectly
+ * overwriting an application written to the incorrect slot.
+ * This feature is only supported by ARM platforms.
+ */
+ if (area_id == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) {
+ const struct flash_area *pri_fa = BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT);
+ struct image_header *secondary_hdr = boot_img_hdr(state, slot);
+ uint32_t reset_value = 0;
+ uint32_t reset_addr = secondary_hdr->ih_hdr_size + sizeof(reset_value);
+
+ rc = flash_area_read(fap, reset_addr, &reset_value, sizeof(reset_value));
+ if (rc != 0) {
+ fih_rc = fih_int_encode(1);
+ goto out;
+ }
+
+ if (reset_value < pri_fa->fa_off || reset_value> (pri_fa->fa_off + pri_fa->fa_size)) {
+ BOOT_LOG_ERR("Reset address of image in secondary slot is not in the primary slot");
+ BOOT_LOG_ERR("Erasing image from secondary slot");
+
+ /* The vector table in the image located in the secondary
+ * slot does not target the primary slot. This might
+ * indicate that the image was loaded to the wrong slot.
+ *
+ * Erase the image and continue booting from the primary slot.
+ */
+ flash_area_erase(fap, 0, fap->fa_size);
+ fih_rc = fih_int_encode(1);
+ goto out;
+ }
+ }
+#endif
+
out:
flash_area_close(fap);