Skip to content

Commit

Permalink
Merge branch 'bugfix/bootloader_iram_overlap_check_v3.0' into 'releas…
Browse files Browse the repository at this point in the history
…e/v3.0'

bootloader: verify that loaded image does not overlap bootloader code (backport v3.0)

See merge request idf/esp-idf!3527
  • Loading branch information
projectgus committed Nov 1, 2018
2 parents 099ae5a + db22238 commit bb56d86
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 6 deletions.
2 changes: 2 additions & 0 deletions components/bootloader/subproject/main/esp32.bootloader.ld
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ SECTIONS
.iram1.text :
{
. = ALIGN (16);
_loader_text_start = ABSOLUTE(.);
*(.entry.text)
*(.init.literal)
*(.init)
Expand Down Expand Up @@ -126,6 +127,7 @@ SECTIONS
*(.fini)
*(.gnu.version)
_text_end = ABSOLUTE(.);
_loader_text_end = ABSOLUTE(.);
_etext = .;
} > iram_seg

Expand Down
34 changes: 34 additions & 0 deletions components/bootloader_support/include/bootloader_util.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include <stddef.h>

/**
* @brief Check if half-open intervals overlap
*
* @param start1 interval 1 start
* @param end1 interval 1 end
* @param start2 interval 2 start
* @param end2 interval 2 end
* @return true iff [start1; end1) overlaps [start2; end2)
*/
static inline bool bootloader_util_regions_overlap(
const intptr_t start1, const intptr_t end1,
const intptr_t start2, const intptr_t end2)
{
return (end1 > start2 && end2 > start1) ||
!(end1 <= start2 || end2 <= start1);
}
40 changes: 34 additions & 6 deletions components/bootloader_support/src/esp_image_format.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <bootloader_flash.h>
#include <bootloader_random.h>
#include <bootloader_sha.h>
#include "bootloader_util.h"

static const char *TAG = "esp_image";

Expand All @@ -42,6 +43,10 @@ static const char *TAG = "esp_image";
(Means loaded code isn't executable until after the secure boot check.)
*/
static uint32_t ram_obfs_value[2];

/* Range of IRAM used by the loader, defined in ld script */
extern int _loader_text_start;
extern int _loader_text_end;
#endif

/* Return true if load_addr is an address the bootloader should load into */
Expand Down Expand Up @@ -286,18 +291,41 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
(do_load)?"load":(is_mapping)?"map":"");
}


#ifdef BOOTLOADER_BUILD
/* Before loading segment, check it doesn't clobber bootloader RAM. */
if (do_load) {
/* Before loading segment, check it doesn't clobber bootloader RAM... */
uint32_t end_addr = load_addr + data_len;
if (end_addr < 0x40000000) {
const intptr_t load_end = load_addr + data_len;
if (load_end <= (intptr_t) SOC_DIRAM_DRAM_HIGH) {
/* Writing to DRAM */
intptr_t sp = (intptr_t)get_sp();
if (end_addr > sp - STACK_LOAD_HEADROOM) {
ESP_LOGE(TAG, "Segment %d end address 0x%08x too high (bootloader stack 0x%08x liimit 0x%08x)",
index, end_addr, sp, sp - STACK_LOAD_HEADROOM);
if (load_end > sp - STACK_LOAD_HEADROOM) {
/* Bootloader .data/.rodata/.bss is above the stack, so this
* also checks that we aren't overwriting these segments.
*
* TODO: This assumes specific arrangement of sections we have
* in the ESP32. Rewrite this in a generic way to support other
* layouts.
*/
ESP_LOGE(TAG, "Segment %d end address 0x%08x too high (bootloader stack 0x%08x limit 0x%08x)",
index, load_end, sp, sp - STACK_LOAD_HEADROOM);
return ESP_ERR_IMAGE_INVALID;
}
} else {
/* Writing to IRAM */
const intptr_t loader_iram_start = (intptr_t) &_loader_text_start;
const intptr_t loader_iram_end = (intptr_t) &_loader_text_end;

if (bootloader_util_regions_overlap(loader_iram_start, loader_iram_end,
load_addr, load_end)) {
ESP_LOGE(TAG, "Segment %d (0x%08x-0x%08x) overlaps bootloader IRAM (0x%08x-0x%08x)",
index, load_addr, load_end, loader_iram_start, loader_iram_end);
return ESP_ERR_IMAGE_INVALID;
}
}
}
#endif // BOOTLOADER_BUILD

#ifndef BOOTLOADER_BUILD
uint32_t free_page_count = spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA);
ESP_LOGD(TAG, "free data page_count 0x%08x",free_page_count);
Expand Down
19 changes: 19 additions & 0 deletions components/bootloader_support/test/test_verify_image.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "freertos/xtensa_api.h"
#include "unity.h"

#include "bootloader_util.h"
#include "esp_partition.h"
#include "esp_ota_ops.h"
#include "esp_image_format.h"
Expand Down Expand Up @@ -47,3 +48,21 @@ TEST_CASE("Verify unit test app image", "[bootloader_support]")
TEST_ASSERT_TRUE(data.image_len <= running->size);
}

TEST_CASE("Test regions_overlap", "[bootloader_support]")
{
TEST_ASSERT( bootloader_util_regions_overlap(1, 2, 1, 2) );

TEST_ASSERT( bootloader_util_regions_overlap(1, 2, 0, 2) );
TEST_ASSERT( bootloader_util_regions_overlap(1, 2, 1, 3) );
TEST_ASSERT( bootloader_util_regions_overlap(1, 2, 0, 3) );

TEST_ASSERT( bootloader_util_regions_overlap(0, 2, 1, 2) );
TEST_ASSERT( bootloader_util_regions_overlap(1, 3, 1, 2) );
TEST_ASSERT( bootloader_util_regions_overlap(0, 3, 1, 2) );

TEST_ASSERT( !bootloader_util_regions_overlap(2, 3, 1, 2) );
TEST_ASSERT( !bootloader_util_regions_overlap(1, 2, 2, 3) );

TEST_ASSERT( !bootloader_util_regions_overlap(3, 4, 1, 2) );
TEST_ASSERT( !bootloader_util_regions_overlap(1, 2, 3, 4) );
}

0 comments on commit bb56d86

Please sign in to comment.