mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'bugfix/s3_memprot_exec_test' into 'master'
Fix(Security): Fixed ESP32S3 Memprot RTCFAST code-execution tests Closes IDF-10719 See merge request espressif/esp-idf!32649
This commit is contained in:
commit
f1492a97a2
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -21,20 +21,26 @@
|
||||
* ESP32S3 MEMORY PROTECTION MODULE TEST
|
||||
* =====================================
|
||||
*
|
||||
* In order to safely test all the memprot features, this test application uses memprot default settings
|
||||
* plus proprietary testing buffers:
|
||||
* - s_iram_test_buffer (.iram_end_test, 1kB) - all IRAM/DRAM low region operations, test-only section
|
||||
* - s_dram_test_buffer (.dram0.data, 1kB) - all IRAM/DRAM high region operations, standard section
|
||||
* - s_rtc_text_test_buffer (.rtc_text_end_test, 1kB) - all RTCFAST low region operations, test-only section
|
||||
* - s_rtc_data_test_buffer (.rtc.data, 1kB) - all RTCFAST high region operations, standard section
|
||||
* Testing addresses are set to the middle of the testing buffers:
|
||||
* In order to safely test all the memory protection features in guarded regions, this test application uses the default Memprot settings,
|
||||
* and deploys the following buffers and testing sections:
|
||||
* - s_iram_test_buffer (.iram_end_test, 1kB) - all IRAM/DRAM low region operations, test-only section, code
|
||||
* - s_dram_test_buffer (.dram0.data, 1kB) - all IRAM/DRAM high region operations, standard section, data
|
||||
* - s_rtc_text_test_buffer (.rtc_text_end_test, 1kB) - all RTCFAST low region operations, test-only section, code
|
||||
* - s_rtc_data_test_buffer (.rtc.force_fast, 1kB) - all RTCFAST high region operations, standard section, data
|
||||
* The testing addresses are used for direct verification of R/W/X permissions setup, as given by the Memprot default setup
|
||||
* for each memory type guarded
|
||||
* The addresses are set to the "middle" of the testing buffers:
|
||||
* - test_ptr_low = (s_iram_test_buffer | s_rtc_text_test_buffer) + 0x200
|
||||
* - test_ptr_high = (s_dram_test_buffer | s_rtc_data_test_buffer) + 0x200
|
||||
* Each operation is tested at both low & high region addresses.
|
||||
* Each test result checked against expected status of PMS violation interrupt status and
|
||||
* against expected value stored in the memory tested (where applicable)
|
||||
* Each operation is tested at both low & high regions, though each section is considered a standalone test
|
||||
* Each test result is checked against expected status of the PMS violation interrupt and possibly
|
||||
* against expected value possibly stored at the concerned address
|
||||
*
|
||||
* Testing scheme is depicted below:
|
||||
* NOTE: RTCFAST split-line is always set to _rtc_text_end address, unlike D/IRAM memory (configurable split-lines). Always check
|
||||
* the corresponding MAP file for real addresses, offsets and alignments, or/and to verify given section existence
|
||||
* (see the GNU LD manual for memory sections generation rules)
|
||||
*
|
||||
* The testing memory disposition is depicted below:
|
||||
*
|
||||
* DRam0/DMA IRam0
|
||||
* -----------------------------------------------
|
||||
@ -46,7 +52,7 @@
|
||||
* DRam0_DMA_line0_Split_addr | -- test_ptr_low -- | =
|
||||
* = =============================================== IRam0_line0_Split_addr
|
||||
* DRam0_DMA_line1_Split_addr | | =
|
||||
* | - - - - - - - s_dram_test_buffer - - - - - --| IRam0_DRam0_Split_addr (main I/D)
|
||||
* | - - - - - - - s_dram_test_buffer - - - - - -| IRam0_DRam0_Split_addr (main I/D)
|
||||
* | -- test_ptr_high -- |
|
||||
* | - - - - - - - - - - - - - - - - - - - - - - |
|
||||
* | |
|
||||
@ -55,21 +61,19 @@
|
||||
* | |
|
||||
* | ... |
|
||||
* | |
|
||||
* =============================================== SOC_RTC_IRAM_LOW (0x50000000)
|
||||
* =============================================== SOC_RTC_IRAM_LOW (0x600FE000)
|
||||
* | -- test_ptr_low -- |
|
||||
* | - - - - - - s_rtc_text_test_buffer - - - - -| RtcFast_Split_addr (_rtc_text_end)
|
||||
* | -- .rtc.dummy -- | (UNUSED - PADDING)
|
||||
* 8 kB | - - - - - - - - - - - - - - - - - - - - - - | [_rtc_dummy_end = _rtc_force_fast_start]
|
||||
* | -- .rtc.force_fast -- | (NOT USED IN THIS TEST)
|
||||
* | - - - - - - s_rtc_data_test_buffer - - - - -| [_rtc_force_fast_end = _rtc_data_start]
|
||||
* | -- test_ptr_high -- |
|
||||
* | - - - - - - - - - - - - - - - - - - - - - - |
|
||||
* =============================================== SOC_RTC_IRAM_HIGH (0x50001FFF)
|
||||
* | .rtc.text | RTC FAST code (s_rtc_text_test_buffer, own rtc_text_end_test section)
|
||||
* | |
|
||||
* -----------------------------------------------
|
||||
* 8 kB | - - - - - - - - - - - - - - - - - - - - - - | RtcFast_Split_addr (_rtc_text_end, fixed)
|
||||
* | -- test_ptr_high -- | [_rtc_text_end = _rtc_force_fast_start]
|
||||
* | .rtc.force_fast |
|
||||
* | | RTC FAST data (s_rtc_data_test_buffer)
|
||||
* | - - - - - - - - - - - - - - - - - - - - - - |
|
||||
* | ... |
|
||||
* ===============================================
|
||||
*/
|
||||
|
||||
|
||||
/* !!!IMPORTANT!!!
|
||||
* a0 needs to be saved/restored manually (not clobbered) to avoid return address corruption
|
||||
* caused by ASM block handling
|
||||
@ -96,41 +100,39 @@
|
||||
ret.n
|
||||
*/
|
||||
|
||||
/* disabled unless IDF-5519 gets merged */
|
||||
//static uint8_t s_fnc_buff[] = {0xf0, 0x22, 0x11, 0x0d, 0xf0, 0x00, 0x00, 0x00};
|
||||
static uint8_t s_fnc_buff[] = {0xf0, 0x22, 0x11, 0x0d, 0xf0, 0x00, 0x00, 0x00};
|
||||
typedef int (*fnc_ptr)(int);
|
||||
|
||||
//testing buffers
|
||||
#define SRAM_TEST_BUFFER_SIZE 0x400
|
||||
#define SRAM_TEST_OFFSET 0x200
|
||||
#define MEMPROT_TEST_BUFFER_SIZE 0x400
|
||||
#define MEMPROT_TEST_OFFSET 0x200
|
||||
|
||||
static uint8_t __attribute__((section(".iram_end_test"))) s_iram_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0};
|
||||
static uint8_t __attribute__((section(".rtc_text_end_test"))) s_rtc_text_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0};
|
||||
static uint8_t RTC_DATA_ATTR s_rtc_data_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0};
|
||||
static uint8_t s_dram_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0};
|
||||
static uint8_t __attribute__((section(".iram_end_test"))) s_iram_test_buffer[MEMPROT_TEST_BUFFER_SIZE] = {0};
|
||||
static uint8_t __attribute__((section(".rtc_text_end_test"))) s_rtc_code_test_buffer[MEMPROT_TEST_BUFFER_SIZE] = {0};
|
||||
static uint8_t RTC_FAST_ATTR s_rtc_data_test_buffer[MEMPROT_TEST_BUFFER_SIZE] = {0};
|
||||
static uint8_t s_dram_test_buffer[MEMPROT_TEST_BUFFER_SIZE] = {0};
|
||||
|
||||
//auxiliary defines
|
||||
#define LOW_REGION true
|
||||
#define HIGH_REGION false
|
||||
#define READ_ENA true
|
||||
#define READ_DIS false
|
||||
#define WRITE_ENA true
|
||||
#define WRITE_DIS false
|
||||
#define EXEC_ENA true
|
||||
#define EXEC_DIS false
|
||||
#define LOW_REGION true
|
||||
#define HIGH_REGION false
|
||||
#define READ_ENA true
|
||||
#define READ_DIS false
|
||||
#define WRITE_ENA true
|
||||
#define WRITE_DIS false
|
||||
#define EXEC_ENA true
|
||||
#define EXEC_DIS false
|
||||
|
||||
volatile bool g_override_illegal_instruction;
|
||||
|
||||
|
||||
static void *test_mprot_addr_low(esp_mprot_mem_t mem_type)
|
||||
{
|
||||
switch (mem_type) {
|
||||
case MEMPROT_TYPE_IRAM0_SRAM:
|
||||
return (void *)((uint32_t)s_iram_test_buffer + SRAM_TEST_OFFSET);
|
||||
return (void *)((uint32_t)s_iram_test_buffer + MEMPROT_TEST_OFFSET);
|
||||
case MEMPROT_TYPE_DRAM0_SRAM:
|
||||
return (void *)MAP_IRAM_TO_DRAM((uint32_t)s_iram_test_buffer + SRAM_TEST_OFFSET);
|
||||
return (void *)MAP_IRAM_TO_DRAM((uint32_t)s_iram_test_buffer + MEMPROT_TEST_OFFSET);
|
||||
case MEMPROT_TYPE_IRAM0_RTCFAST:
|
||||
return (void *)((uint32_t)s_rtc_text_test_buffer + SRAM_TEST_OFFSET);
|
||||
return (void *)((uint32_t)s_rtc_code_test_buffer + MEMPROT_TEST_OFFSET);
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
@ -140,11 +142,11 @@ static void *test_mprot_addr_high(esp_mprot_mem_t mem_type)
|
||||
{
|
||||
switch (mem_type) {
|
||||
case MEMPROT_TYPE_IRAM0_SRAM:
|
||||
return (void *)MAP_DRAM_TO_IRAM((uint32_t)s_dram_test_buffer + SRAM_TEST_OFFSET);
|
||||
return (void *)MAP_DRAM_TO_IRAM((uint32_t)s_dram_test_buffer + MEMPROT_TEST_OFFSET);
|
||||
case MEMPROT_TYPE_DRAM0_SRAM:
|
||||
return (void *)((uint32_t)s_dram_test_buffer + SRAM_TEST_OFFSET);
|
||||
return (void *)((uint32_t)s_dram_test_buffer + MEMPROT_TEST_OFFSET);
|
||||
case MEMPROT_TYPE_IRAM0_RTCFAST:
|
||||
return (void *)((uint32_t)s_rtc_data_test_buffer + SRAM_TEST_OFFSET);
|
||||
return (void *)((uint32_t)s_rtc_data_test_buffer + MEMPROT_TEST_OFFSET);
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
@ -192,7 +194,7 @@ static void __attribute__((unused)) test_mprot_dump_status_register(esp_mprot_me
|
||||
}
|
||||
}
|
||||
|
||||
esp_rom_printf( "]\n" );
|
||||
esp_rom_printf("]\n");
|
||||
}
|
||||
|
||||
static void test_mprot_check_test_result(esp_mprot_mem_t mem_type, bool expected_status)
|
||||
@ -359,7 +361,7 @@ static void test_mprot_read(esp_mprot_mem_t mem_type, const int core)
|
||||
test_mprot_set_permissions(LOW_REGION, mem_type, read_perm_low, write_perm_low, is_exec_mem ? &exec_perm_low : NULL, core);
|
||||
test_mprot_set_permissions(HIGH_REGION, mem_type, read_perm_high, write_perm_high, is_exec_mem ? &exec_perm_high : NULL, core);
|
||||
|
||||
//reenable monitoring
|
||||
//re-enable monitoring
|
||||
err = esp_mprot_set_monitor_en(mem_type, true, core);
|
||||
if (err != ESP_OK) {
|
||||
esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_read\n", esp_err_to_name(err));
|
||||
@ -377,7 +379,7 @@ static void test_mprot_read(esp_mprot_mem_t mem_type, const int core)
|
||||
volatile uint32_t val = *ptr_low;
|
||||
|
||||
if (read_perm_low && val != test_val) {
|
||||
esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val );
|
||||
esp_rom_printf("UNEXPECTED VALUE 0x%08X -", val);
|
||||
test_mprot_dump_status_register(mem_type, core);
|
||||
} else {
|
||||
test_mprot_check_test_result(mem_type, read_perm_low);
|
||||
@ -394,14 +396,13 @@ static void test_mprot_read(esp_mprot_mem_t mem_type, const int core)
|
||||
val = *ptr_high;
|
||||
|
||||
if (read_perm_high && val != (test_val + 1)) {
|
||||
esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val);
|
||||
esp_rom_printf("UNEXPECTED VALUE 0x%08X -", val);
|
||||
test_mprot_dump_status_register(mem_type, core);
|
||||
} else {
|
||||
test_mprot_check_test_result(mem_type, read_perm_high);
|
||||
}
|
||||
|
||||
esp_mprot_monitor_clear_intr(mem_type, core);
|
||||
//test_mprot_dump_status_register(mem_type, core);
|
||||
}
|
||||
|
||||
static void test_mprot_write(esp_mprot_mem_t mem_type, const int core)
|
||||
@ -451,7 +452,7 @@ static void test_mprot_write(esp_mprot_mem_t mem_type, const int core)
|
||||
val = *ptr_low;
|
||||
|
||||
if (write_perm_low && val != test_val) {
|
||||
esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val);
|
||||
esp_rom_printf("UNEXPECTED VALUE 0x%08X -", val);
|
||||
test_mprot_dump_status_register(mem_type, core);
|
||||
} else {
|
||||
test_mprot_check_test_result(mem_type, write_perm_low);
|
||||
@ -470,7 +471,7 @@ static void test_mprot_write(esp_mprot_mem_t mem_type, const int core)
|
||||
val = *ptr_high;
|
||||
|
||||
if (val != (test_val + 1) && write_perm_high) {
|
||||
esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val);
|
||||
esp_rom_printf("UNEXPECTED VALUE 0x%08X -", val);
|
||||
test_mprot_dump_status_register(mem_type, core);
|
||||
} else {
|
||||
test_mprot_check_test_result(mem_type, write_perm_high);
|
||||
@ -495,11 +496,10 @@ static void test_mprot_write(esp_mprot_mem_t mem_type, const int core)
|
||||
esp_mprot_monitor_clear_intr(mem_type, core);
|
||||
}
|
||||
|
||||
#if 0 /* disabled unless IDF-5519 gets merged */
|
||||
static void test_mprot_exec(esp_mprot_mem_t mem_type, const int core)
|
||||
{
|
||||
if (!(mem_type & MEMPROT_TYPE_IRAM0_ANY)) {
|
||||
esp_rom_printf("Error: EXEC test available only for IRAM access.\n" );
|
||||
esp_rom_printf("Error: EXEC test available only for IRAM access.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -538,7 +538,7 @@ static void test_mprot_exec(esp_mprot_mem_t mem_type, const int core)
|
||||
fnc_ptr_low = (void *) MAP_DRAM_TO_IRAM(fnc_ptr_low);
|
||||
fnc_ptr_high = (void *) MAP_DRAM_TO_IRAM(fnc_ptr_high);
|
||||
|
||||
//reenable DBUS protection
|
||||
//re-enable DBUS protection
|
||||
test_mprot_set_permissions(LOW_REGION, MEMPROT_TYPE_DRAM0_SRAM, READ_ENA, WRITE_DIS, NULL, core);
|
||||
} else if (mem_type == MEMPROT_TYPE_IRAM0_RTCFAST) {
|
||||
//enable WRITE for low region
|
||||
@ -551,7 +551,7 @@ static void test_mprot_exec(esp_mprot_mem_t mem_type, const int core)
|
||||
memcpy(fnc_ptr_low, (const void *) s_fnc_buff, sizeof(s_fnc_buff));
|
||||
memcpy(fnc_ptr_high, (const void *) s_fnc_buff, sizeof(s_fnc_buff));
|
||||
|
||||
//reenable original protection
|
||||
//re-enable original protection
|
||||
test_mprot_set_permissions(LOW_REGION, MEMPROT_TYPE_IRAM0_RTCFAST, read_perm_low, write_perm_low, &exec_perm_low, core);
|
||||
} else {
|
||||
assert(0);
|
||||
@ -618,7 +618,6 @@ static void test_mprot_exec(esp_mprot_mem_t mem_type, const int core)
|
||||
|
||||
esp_mprot_monitor_clear_intr(mem_type, core);
|
||||
}
|
||||
#endif
|
||||
|
||||
// testing per-CPU tasks
|
||||
esp_memp_config_t memp_cfg = {
|
||||
@ -647,8 +646,7 @@ static void task_on_CPU(void *arg)
|
||||
if (memp_cfg.mem_type_mask & MEMPROT_TYPE_IRAM0_SRAM) {
|
||||
test_mprot_read(MEMPROT_TYPE_IRAM0_SRAM, ctx->core);
|
||||
test_mprot_write(MEMPROT_TYPE_IRAM0_SRAM, ctx->core);
|
||||
/* disabled unless IDF-5519 gets merged */
|
||||
//test_mprot_exec(MEMPROT_TYPE_IRAM0_SRAM, ctx->core);
|
||||
test_mprot_exec(MEMPROT_TYPE_IRAM0_SRAM, ctx->core);
|
||||
}
|
||||
|
||||
if (memp_cfg.mem_type_mask & MEMPROT_TYPE_DRAM0_SRAM) {
|
||||
@ -659,8 +657,7 @@ static void task_on_CPU(void *arg)
|
||||
if (memp_cfg.mem_type_mask & MEMPROT_TYPE_IRAM0_RTCFAST) {
|
||||
test_mprot_read(MEMPROT_TYPE_IRAM0_RTCFAST, ctx->core);
|
||||
test_mprot_write(MEMPROT_TYPE_IRAM0_RTCFAST, ctx->core);
|
||||
/* disabled unless IDF-5519 gets merged */
|
||||
//test_mprot_exec(MEMPROT_TYPE_IRAM0_RTCFAST, ctx->core);
|
||||
test_mprot_exec(MEMPROT_TYPE_IRAM0_RTCFAST, ctx->core);
|
||||
}
|
||||
|
||||
xSemaphoreGive(ctx->sem);
|
||||
|
@ -1,6 +1,5 @@
|
||||
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
import logging
|
||||
|
||||
import pytest
|
||||
@ -23,24 +22,19 @@ MEM_TEST_UNICORE = {
|
||||
],
|
||||
'esp32s3': [
|
||||
['IRAM0_SRAM (core 0)', 'WRX'],
|
||||
['DRAM0_SRAM (core 0)', 'WR']
|
||||
# temporarily disabled unless IDF-5208 gets merged
|
||||
# ['IRAM0_RTCFAST', 'WR'],
|
||||
['DRAM0_SRAM (core 0)', 'WR'],
|
||||
['IRAM0_RTCFAST (core 0)', 'WRX']
|
||||
],
|
||||
}
|
||||
|
||||
MEM_TEST_MULTICORE = {
|
||||
'esp32s3': [
|
||||
# instruction execute test temporarily disabled
|
||||
# ['IRAM0_SRAM (core 0)', 'WRX'],
|
||||
['IRAM0_SRAM (core 0)', 'WR'],
|
||||
['IRAM0_SRAM (core 0)', 'WRX'],
|
||||
['DRAM0_SRAM (core 0)', 'WR'],
|
||||
# instruction execute test temporarily disabled
|
||||
# ['IRAM0_SRAM (core 1)', 'WRX'],
|
||||
['IRAM0_SRAM (core 1)', 'WR'],
|
||||
['DRAM0_SRAM (core 1)', 'WR']
|
||||
# temporarily disabled unless IDF-5208 gets merged
|
||||
# ['IRAM0_RTCFAST', 'WR'],
|
||||
['IRAM0_RTCFAST (core 0)', 'WRX'],
|
||||
['IRAM0_SRAM (core 1)', 'WRX'],
|
||||
['DRAM0_SRAM (core 1)', 'WR'],
|
||||
['IRAM0_RTCFAST (core 1)', 'WRX']
|
||||
]
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user