From 95c4491fba9e403627089b07ed8bb3c70d45d606 Mon Sep 17 00:00:00 2001 From: Konstantin Kondrashov Date: Mon, 15 Jun 2026 15:21:31 +0300 Subject: [PATCH 1/4] fix(esp_image_format): Verify image segment count --- .../bootloader_support/src/esp_image_format.c | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/components/bootloader_support/src/esp_image_format.c b/components/bootloader_support/src/esp_image_format.c index d821d63e469..1075e76cbe8 100644 --- a/components/bootloader_support/src/esp_image_format.c +++ b/components/bootloader_support/src/esp_image_format.c @@ -94,7 +94,7 @@ typedef struct { static esp_err_t process_segment_data(const process_segment_data_t *segment_data); /* Verify the main image header */ -static esp_err_t verify_image_header(uint32_t src_addr, const esp_image_header_t *image, bool silent); +static esp_err_t verify_image_header(uint32_t src_addr, const esp_image_header_t *image, bool do_verify, bool silent); /* Verify a segment header */ static esp_err_t verify_segment_header(int index, const esp_image_segment_header_t *segment, uint32_t segment_data_offs, esp_image_metadata_t *metadata, bool silent); @@ -382,7 +382,7 @@ err: return err; } -static esp_err_t verify_image_header(uint32_t src_addr, const esp_image_header_t *image, bool silent) +static esp_err_t verify_image_header(uint32_t src_addr, const esp_image_header_t *image, bool do_verify, bool silent) { esp_err_t err = ESP_OK; @@ -397,11 +397,13 @@ static esp_err_t verify_image_header(uint32_t src_addr, const esp_image_header_t FAIL_LOAD("image at 0x%"PRIx32" has invalid magic byte (nothing flashed here?)", src_addr); } - // Checking the chip revision header *will* print a bunch of other info - // regardless of silent setting as this may be important, but don't bother checking it - // if it looks like the app partition is erased or otherwise garbage - esp_image_type image_type = is_bootloader(src_addr) ? ESP_IMAGE_BOOTLOADER : ESP_IMAGE_APPLICATION; - CHECK_ERR(bootloader_common_check_chip_validity(image, image_type)); + if (do_verify) { + // Checking the chip revision header *will* print a bunch of other info + // regardless of silent setting as this may be important, but don't bother checking it + // if it looks like the app partition is erased or otherwise garbage + esp_image_type image_type = is_bootloader(src_addr) ? ESP_IMAGE_BOOTLOADER : ESP_IMAGE_APPLICATION; + CHECK_ERR(bootloader_common_check_chip_validity(image, image_type)); + } if (image->segment_count > ESP_IMAGE_MAX_SEGMENTS) { FAIL_LOAD("image at 0x%"PRIx32" segment count %d exceeds max %d", src_addr, image->segment_count, ESP_IMAGE_MAX_SEGMENTS); @@ -576,8 +578,10 @@ static esp_err_t process_image_header(esp_image_metadata_t *data, uint32_t part_ bootloader_sha256_data(*sha_handle, &data->image, sizeof(esp_image_header_t)); } } - CHECK_ERR(verify_image_header(data->start_addr, &data->image, silent)); } + + CHECK_ERR(verify_image_header(data->start_addr, &data->image, do_verify, silent)); + data->image_len = sizeof(esp_image_header_t); return ESP_OK; err: From 85d56ea446c583fa6eb36f7c5fa4b12c79f6c2be Mon Sep 17 00:00:00 2001 From: Konstantin Kondrashov Date: Mon, 15 Jun 2026 16:52:17 +0300 Subject: [PATCH 2/4] fix(esp_image_format): verify length of segment #0 for app description --- components/bootloader_support/src/esp_image_format.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/bootloader_support/src/esp_image_format.c b/components/bootloader_support/src/esp_image_format.c index 1075e76cbe8..1a19034a6ee 100644 --- a/components/bootloader_support/src/esp_image_format.c +++ b/components/bootloader_support/src/esp_image_format.c @@ -871,6 +871,10 @@ static esp_err_t verify_segment_header(int index, const esp_image_segment_header /* ESP APP descriptor is present in the DROM segment #0 */ if (index == 0 && !is_bootloader(metadata->start_addr)) { + if (segment->data_len < sizeof(esp_app_desc_t)) { + ESP_LOGE(TAG, "Segment %d: length 0x%"PRIx32" is too short for app description", index, segment->data_len); + return ESP_ERR_IMAGE_INVALID; + } uint32_t mmu_page_size = 0, magic_word = 0; const uint32_t mmu_page_size_offset = segment_data_offs + offsetof(esp_app_desc_t, mmu_page_size); CHECK_ERR(bootloader_flash_read(segment_data_offs, &magic_word, sizeof(uint32_t), true)); From 777c72a01ec30ea3310458e3cd35f5e8e3d6040e Mon Sep 17 00:00:00 2001 From: Konstantin Kondrashov Date: Tue, 23 Jun 2026 18:16:20 +0300 Subject: [PATCH 3/4] fix(esp_image_format): validate MMU page size --- .../bootloader_support/src/esp_image_format.c | 27 +++++++++++++++---- components/hal/include/hal/mmu_types.h | 2 ++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/components/bootloader_support/src/esp_image_format.c b/components/bootloader_support/src/esp_image_format.c index 1a19034a6ee..93c7b97ffac 100644 --- a/components/bootloader_support/src/esp_image_format.c +++ b/components/bootloader_support/src/esp_image_format.c @@ -21,6 +21,7 @@ #include "esp_app_desc.h" #include "bootloader_memory_utils.h" #include "soc/soc_caps.h" +#include "hal/mmu_types.h" #include "hal/cache_ll.h" #include "spi_flash_mmap.h" #include "hal/efuse_hal.h" @@ -813,6 +814,10 @@ static esp_err_t process_segment_data(const process_segment_data_t *segment_data ESP_LOGD(TAG, "additional anti-rollback check 0x%"PRIx32, segment_data->data_addr); size_t len = process_esp_app_desc_data(src, segment_data->sha_handle, segment_data->checksum, segment_data->metadata); + if (len > data_len) { + bootloader_munmap(data); + return ESP_ERR_IMAGE_INVALID; + } data_len -= len; src += len / 4; // In BOOTLOADER_BUILD, for DROM (segment #0) we do not load it into dest (only map it), do_load = false. @@ -866,15 +871,19 @@ static esp_err_t verify_segment_header(int index, const esp_image_segment_header uint32_t load_addr = segment->load_addr; bool map_segment = should_map(load_addr); -#if SOC_MMU_PAGE_SIZE_CONFIGURABLE - esp_err_t err = ESP_FAIL; - - /* ESP APP descriptor is present in the DROM segment #0 */ + // Validate minimum length for segment #0 if (index == 0 && !is_bootloader(metadata->start_addr)) { if (segment->data_len < sizeof(esp_app_desc_t)) { ESP_LOGE(TAG, "Segment %d: length 0x%"PRIx32" is too short for app description", index, segment->data_len); return ESP_ERR_IMAGE_INVALID; } + } + +#if SOC_MMU_PAGE_SIZE_CONFIGURABLE + esp_err_t err = ESP_FAIL; + + /* ESP APP descriptor is present in the DROM segment #0 */ + if (index == 0 && !is_bootloader(metadata->start_addr)) { uint32_t mmu_page_size = 0, magic_word = 0; const uint32_t mmu_page_size_offset = segment_data_offs + offsetof(esp_app_desc_t, mmu_page_size); CHECK_ERR(bootloader_flash_read(segment_data_offs, &magic_word, sizeof(uint32_t), true)); @@ -888,7 +897,15 @@ static esp_err_t verify_segment_header(int index, const esp_image_segment_header } // Convert from log base 2 number to actual size while handling legacy image case (value 0) - metadata->mmu_page_size = (mmu_page_size > 0) ? (1UL << mmu_page_size) : SPI_FLASH_MMU_PAGE_SIZE; + const uint32_t min_mmu_page_size = __builtin_ctz(MMU_PAGE_SIZE_MIN); + const uint32_t max_mmu_page_size = __builtin_ctz(MMU_PAGE_SIZE_MAX); + if (mmu_page_size >= min_mmu_page_size && mmu_page_size <= max_mmu_page_size) { + metadata->mmu_page_size = (1UL << mmu_page_size); + } else { + // Fall back to default MMU page size + metadata->mmu_page_size = SPI_FLASH_MMU_PAGE_SIZE; + } + if (metadata->mmu_page_size != SPI_FLASH_MMU_PAGE_SIZE) { ESP_LOGI(TAG, "MMU page size mismatch, configured: 0x%x, found: 0x%"PRIx32, SPI_FLASH_MMU_PAGE_SIZE, metadata->mmu_page_size); } diff --git a/components/hal/include/hal/mmu_types.h b/components/hal/include/hal/mmu_types.h index ee42bd5632a..a87e355671a 100644 --- a/components/hal/include/hal/mmu_types.h +++ b/components/hal/include/hal/mmu_types.h @@ -25,9 +25,11 @@ typedef enum { */ typedef enum { MMU_PAGE_8KB = 0x2000, + MMU_PAGE_SIZE_MIN = MMU_PAGE_8KB, MMU_PAGE_16KB = 0x4000, MMU_PAGE_32KB = 0x8000, MMU_PAGE_64KB = 0x10000, + MMU_PAGE_SIZE_MAX = MMU_PAGE_64KB, } mmu_page_size_t; /** From b116ab3a2154feda9cdeb049a810579ceb71d0c4 Mon Sep 17 00:00:00 2001 From: Konstantin Kondrashov Date: Tue, 30 Jun 2026 13:09:34 +0300 Subject: [PATCH 4/4] fix(bootloader): increase partition table offset for ESP32-P4 in affected test configs --- components/efuse/test_apps/sdkconfig.defaults.esp32p4 | 1 + .../sdkconfig.ci.no_rom_impl_components.esp32p4 | 1 + .../bootloader_hooks/sdkconfig.ci.log_v2.esp32p4 | 1 + examples/system/deep_sleep/sdkconfig.defaults.esp32p4 | 1 + examples/system/efuse/sdkconfig.defaults.esp32p4 | 1 + .../system/bootloader_sections/sdkconfig.defaults.esp32p4 | 1 + 6 files changed, 6 insertions(+) create mode 100644 components/efuse/test_apps/sdkconfig.defaults.esp32p4 create mode 100644 components/esp_rom/test_apps/rom_impl_components/sdkconfig.ci.no_rom_impl_components.esp32p4 create mode 100644 examples/custom_bootloader/bootloader_hooks/sdkconfig.ci.log_v2.esp32p4 create mode 100644 examples/system/deep_sleep/sdkconfig.defaults.esp32p4 create mode 100644 examples/system/efuse/sdkconfig.defaults.esp32p4 create mode 100644 tools/test_apps/system/bootloader_sections/sdkconfig.defaults.esp32p4 diff --git a/components/efuse/test_apps/sdkconfig.defaults.esp32p4 b/components/efuse/test_apps/sdkconfig.defaults.esp32p4 new file mode 100644 index 00000000000..d5c0b681054 --- /dev/null +++ b/components/efuse/test_apps/sdkconfig.defaults.esp32p4 @@ -0,0 +1 @@ +CONFIG_PARTITION_TABLE_OFFSET=0x9000 diff --git a/components/esp_rom/test_apps/rom_impl_components/sdkconfig.ci.no_rom_impl_components.esp32p4 b/components/esp_rom/test_apps/rom_impl_components/sdkconfig.ci.no_rom_impl_components.esp32p4 new file mode 100644 index 00000000000..d5c0b681054 --- /dev/null +++ b/components/esp_rom/test_apps/rom_impl_components/sdkconfig.ci.no_rom_impl_components.esp32p4 @@ -0,0 +1 @@ +CONFIG_PARTITION_TABLE_OFFSET=0x9000 diff --git a/examples/custom_bootloader/bootloader_hooks/sdkconfig.ci.log_v2.esp32p4 b/examples/custom_bootloader/bootloader_hooks/sdkconfig.ci.log_v2.esp32p4 new file mode 100644 index 00000000000..d5c0b681054 --- /dev/null +++ b/examples/custom_bootloader/bootloader_hooks/sdkconfig.ci.log_v2.esp32p4 @@ -0,0 +1 @@ +CONFIG_PARTITION_TABLE_OFFSET=0x9000 diff --git a/examples/system/deep_sleep/sdkconfig.defaults.esp32p4 b/examples/system/deep_sleep/sdkconfig.defaults.esp32p4 new file mode 100644 index 00000000000..d5c0b681054 --- /dev/null +++ b/examples/system/deep_sleep/sdkconfig.defaults.esp32p4 @@ -0,0 +1 @@ +CONFIG_PARTITION_TABLE_OFFSET=0x9000 diff --git a/examples/system/efuse/sdkconfig.defaults.esp32p4 b/examples/system/efuse/sdkconfig.defaults.esp32p4 new file mode 100644 index 00000000000..d5c0b681054 --- /dev/null +++ b/examples/system/efuse/sdkconfig.defaults.esp32p4 @@ -0,0 +1 @@ +CONFIG_PARTITION_TABLE_OFFSET=0x9000 diff --git a/tools/test_apps/system/bootloader_sections/sdkconfig.defaults.esp32p4 b/tools/test_apps/system/bootloader_sections/sdkconfig.defaults.esp32p4 new file mode 100644 index 00000000000..d5c0b681054 --- /dev/null +++ b/tools/test_apps/system/bootloader_sections/sdkconfig.defaults.esp32p4 @@ -0,0 +1 @@ +CONFIG_PARTITION_TABLE_OFFSET=0x9000