Skip to content

Commit 75305c2

Browse files
committed
Merge branch 'feat/make-use-of-exec-cap-compile-time-error' into 'master'
feat(heap): Make MALLOC_CAP_EXEC illegal use a compile time error Closes IDFGH-14014 and IDF-11690 See merge request espressif/esp-idf!34903
2 parents 7832985 + 0f3f44b commit 75305c2

File tree

11 files changed

+40
-18
lines changed

11 files changed

+40
-18
lines changed

components/esp_system/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ menu "ESP System Settings"
168168
(above the splitting address). The memory protection is effective on all access
169169
through the IRAM0 and DRAM0 buses.
170170

171+
Note: allocating memory with MALLOC_CAP_EXEC capability is not possible when this config is enabled.
172+
171173
choice ESP_SYSTEM_MEMPROT_MODE
172174
prompt "Memory Protection configurations"
173175
depends on ESP_SYSTEM_MEMPROT

components/heap/Kconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
menu "Heap memory debugging"
22

3+
config HEAP_HAS_EXEC_HEAP
4+
bool
5+
default n if ESP_SYSTEM_MEMPROT
6+
default y if !ESP_SYSTEM_MEMPROT
7+
38
choice HEAP_CORRUPTION_DETECTION
49
prompt "Heap corruption detection"
510
default HEAP_POISONING_DISABLED

components/heap/heap_caps_base.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,9 @@ HEAP_IRAM_ATTR NOINLINE_ATTR void *heap_caps_aligned_alloc_base(size_t alignment
116116
return NULL;
117117
}
118118

119-
if (caps & MALLOC_CAP_EXEC) {
119+
#if CONFIG_HEAP_HAS_EXEC_HEAP
120+
const bool exec_in_caps = caps & MALLOC_CAP_EXEC;
121+
if (exec_in_caps) {
120122
//MALLOC_CAP_EXEC forces an alloc from IRAM. There is a region which has both this as well as the following
121123
//caps, but the following caps are not possible for IRAM. Thus, the combination is impossible and we return
122124
//NULL directly, even although our heap capabilities (based on soc_memory_tags & soc_memory_regions) would
@@ -126,6 +128,9 @@ HEAP_IRAM_ATTR NOINLINE_ATTR void *heap_caps_aligned_alloc_base(size_t alignment
126128
}
127129
caps |= MALLOC_CAP_32BIT; // IRAM is 32-bit accessible RAM
128130
}
131+
#else
132+
const bool exec_in_caps = false;
133+
#endif
129134

130135
if (caps & MALLOC_CAP_32BIT) {
131136
/* 32-bit accessible RAM should allocated in 4 byte aligned sizes
@@ -148,7 +153,7 @@ HEAP_IRAM_ATTR NOINLINE_ATTR void *heap_caps_aligned_alloc_base(size_t alignment
148153
//This heap can satisfy all the requested capabilities. See if we can grab some memory using it.
149154
// If MALLOC_CAP_EXEC is requested but the DRAM and IRAM are on the same addresses (like on esp32c6)
150155
// proceed as for a default allocation.
151-
if ((caps & MALLOC_CAP_EXEC) &&
156+
if (exec_in_caps &&
152157
((!esp_dram_match_iram() && esp_ptr_in_diram_dram((void *)heap->start)) ||
153158
(!esp_rtc_dram_match_rtc_iram() && esp_ptr_in_rtc_dram_fast((void *)heap->start)))) {
154159
//This is special, insofar that what we're going to get back is a DRAM address. If so,

components/heap/include/esp_heap_caps.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ extern "C" {
2626
/**
2727
* @brief Flags to indicate the capabilities of the various memory systems
2828
*/
29+
#if CONFIG_HEAP_HAS_EXEC_HEAP
2930
#define MALLOC_CAP_EXEC (1<<0) ///< Memory must be able to run executable code
31+
#endif
3032
#define MALLOC_CAP_32BIT (1<<1) ///< Memory must allow for aligned 32-bit data accesses
3133
#define MALLOC_CAP_8BIT (1<<2) ///< Memory must allow for 8/16/...-bit data accesses
3234
#define MALLOC_CAP_DMA (1<<3) ///< Memory must be able to accessed by DMA

components/heap/port/esp32s3/memory_layout.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,11 @@ enum {
4444
#ifdef CONFIG_ESP_SYSTEM_MEMPROT
4545
#define MALLOC_DIRAM_BASE_CAPS ESP32S3_MEM_COMMON_CAPS | MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA | MALLOC_CAP_RETENTION
4646
#define MALLOC_RTCRAM_BASE_CAPS ESP32S3_MEM_COMMON_CAPS | MALLOC_CAP_INTERNAL
47+
#define MALLOC_IRAM_BASE_CAPS 0
4748
#else
4849
#define MALLOC_DIRAM_BASE_CAPS ESP32S3_MEM_COMMON_CAPS | MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA | MALLOC_CAP_RETENTION | MALLOC_CAP_EXEC
4950
#define MALLOC_RTCRAM_BASE_CAPS ESP32S3_MEM_COMMON_CAPS | MALLOC_CAP_INTERNAL | MALLOC_CAP_EXEC
51+
#define MALLOC_IRAM_BASE_CAPS MALLOC_CAP_EXEC
5052
#endif
5153

5254
// The memory used for SIMD instructions requires the bus of its memory regions be able to transfer the data in 128-bit
@@ -61,7 +63,7 @@ const soc_memory_type_desc_t soc_memory_types[SOC_MEMORY_TYPE_NUM] = {
6163
/* Mem Type Name | High Priority Matching | Medium Priority Matching | Low Priority Matching */
6264
[SOC_MEMORY_TYPE_DIRAM] = { "RAM", { MALLOC_DIRAM_BASE_CAPS | MALLOC_CAP_SIMD, 0, 0 }},
6365
[SOC_MEMORY_TYPE_DRAM] = { "DRAM", { 0, ESP32S3_MEM_COMMON_CAPS | MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA | MALLOC_CAP_SIMD, 0 }},
64-
[SOC_MEMORY_TYPE_IRAM] = { "IRAM", { MALLOC_CAP_EXEC, MALLOC_CAP_32BIT | MALLOC_CAP_INTERNAL, 0 }},
66+
[SOC_MEMORY_TYPE_IRAM] = { "IRAM", { MALLOC_IRAM_BASE_CAPS, MALLOC_CAP_32BIT | MALLOC_CAP_INTERNAL, 0 }},
6567
[SOC_MEMORY_TYPE_SPIRAM] = { "SPIRAM", { MALLOC_CAP_SPIRAM, 0, ESP32S3_MEM_COMMON_CAPS | MALLOC_CAP_SIMD }},
6668
[SOC_MEMORY_TYPE_RTCRAM] = { "RTCRAM", { MALLOC_CAP_RTCRAM, 0, MALLOC_RTCRAM_BASE_CAPS }},
6769
};

components/heap/test_apps/heap_tests/main/test_aligned_alloc_caps.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,6 @@ TEST_CASE("Capabilities aligned allocator test", "[heap][psram]")
4545
}
4646
}
4747

48-
//Alloc from a non permitted area:
49-
uint32_t *not_permitted_buf = (uint32_t *)heap_caps_aligned_alloc(alignments, (alignments + 137), MALLOC_CAP_EXEC | MALLOC_CAP_32BIT);
50-
TEST_ASSERT( not_permitted_buf == NULL );
51-
5248
#if CONFIG_SPIRAM
5349
alignments = 0;
5450
printf("[ALIGNED_ALLOC] Allocating from external memory: \n");

components/heap/test_apps/heap_tests/main/test_diram.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
#define ALLOC_SZ 1024
1717

18-
#if !CONFIG_ESP_SYSTEM_MEMPROT
18+
#if CONFIG_HEAP_HAS_EXEC_HEAP
1919
static void *malloc_block_diram(uint32_t caps)
2020
{
2121
void *attempts[256] = { 0 }; // Allocate up to 256 ALLOC_SZ blocks to exhaust all non-D/IRAM memory temporarily
@@ -78,4 +78,4 @@ TEST_CASE("Allocate D/IRAM as IRAM", "[heap][qemu-ignore]")
7878

7979
free(iram);
8080
}
81-
#endif // !CONFIG_ESP_SYSTEM_MEMPROT
81+
#endif // CONFIG_HEAP_HAS_EXEC_HEAP

components/heap/test_apps/heap_tests/main/test_malloc.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,9 @@ TEST_CASE("alloc overflows should all fail", "[heap]")
154154
/* will overflow when the size is rounded up to word align it */
155155
TEST_ASSERT_NULL(heap_caps_malloc(SIZE_MAX-1, MALLOC_CAP_32BIT));
156156

157+
#if CONFIG_HEAP_HAS_EXEC_HEAP
157158
TEST_ASSERT_NULL(heap_caps_malloc(SIZE_MAX-1, MALLOC_CAP_EXEC));
159+
#endif
158160
}
159161

160162
TEST_CASE("unreasonable allocs should all fail", "[heap]")

components/heap/test_apps/heap_tests/main/test_malloc_caps.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#include <stdlib.h>
1919
#include <sys/param.h>
2020

21-
#if !CONFIG_ESP_SYSTEM_MEMPROT && !CONFIG_HEAP_TASK_TRACKING
21+
#if CONFIG_HEAP_HAS_EXEC_HEAP && !(CONFIG_HEAP_TASK_TRACKING)
2222
TEST_CASE("Capabilities allocator test", "[heap]")
2323
{
2424
char *m1, *m2[10];
@@ -108,7 +108,7 @@ TEST_CASE("Capabilities allocator test", "[heap]")
108108
free(m1);
109109
printf("Done.\n");
110110
}
111-
#endif // !CONFIG_ESP_SYSTEM_MEMPROT && !CONFIG_HEAP_TASK_TRACKING
111+
#endif // CONFIG_HEAP_HAS_EXEC_HEAP && !(CONFIG_HEAP_TASK_TRACKING)
112112

113113
#ifdef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY
114114
TEST_CASE("IRAM_8BIT capability test", "[heap]")
@@ -230,7 +230,7 @@ TEST_CASE("heap caps minimum free bytes fault cases", "[heap]")
230230
/* Small function runs from IRAM to check that malloc/free/realloc
231231
all work OK when cache is disabled...
232232
*/
233-
#if !CONFIG_ESP_SYSTEM_MEMPROT && !CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH && !CONFIG_HEAP_TASK_TRACKING
233+
#if CONFIG_HEAP_HAS_EXEC_HEAP && !CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH && !CONFIG_HEAP_TASK_TRACKING
234234
static IRAM_ATTR __attribute__((noinline)) bool iram_malloc_test(void)
235235
{
236236
spi_flash_guard_get()->start(); // Disables flash cache
@@ -252,7 +252,7 @@ TEST_CASE("heap_caps_xxx functions work with flash cache disabled", "[heap]")
252252
{
253253
TEST_ASSERT( iram_malloc_test() );
254254
}
255-
#endif // !CONFIG_ESP_SYSTEM_MEMPROT && !CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH && !CONFIG_HEAP_TASK_TRACKING
255+
#endif // CONFIG_HEAP_HAS_EXEC_HEAP && !CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH && !CONFIG_HEAP_TASK_TRACKING
256256

257257
#ifdef CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS
258258
TEST_CASE("When enabled, allocation operation failure generates an abort", "[heap][reset=abort,SW_CPU_RESET]")
@@ -336,22 +336,19 @@ TEST_CASE("RTC memory should be lowest priority and its free size should be big
336336
}
337337
#endif
338338

339+
#if CONFIG_HEAP_HAS_EXEC_HEAP
339340
TEST_CASE("test memory protection features", "[heap][mem_prot]")
340341
{
341342
// try to allocate memory in IRAM and check that if memory protection is active,
342343
// no memory is being allocated
343344
uint32_t *iram_ptr = heap_caps_malloc(4, MALLOC_CAP_EXEC);
344345

345-
#if !CONFIG_ESP_SYSTEM_MEMPROT
346346
// System memory protection not active, check that iram_ptr is not null
347347
// Check that iram_ptr is in IRAM
348348
TEST_ASSERT_NOT_NULL(iram_ptr);
349349
TEST_ASSERT(true == esp_ptr_in_iram(iram_ptr));
350350

351351
// free the memory
352352
heap_caps_free(iram_ptr);
353-
#else
354-
// System memory protection is active, DIRAM seen as DRAM, iram_ptr should be null
355-
TEST_ASSERT_NULL(iram_ptr);
356-
#endif // !CONFIG_ESP_SYSTEM_MEMPROT
357353
}
354+
#endif // CONFIG_HEAP_HAS_EXEC_HEAP

docs/en/migration-guides/release-6.x/6.0/system.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,3 +246,10 @@ ULP
246246
---
247247

248248
The LP-Core will now wake up the main CPU when it encounters an exception during deep sleep. This feature is enabled by default but can be disabled via the :ref:`CONFIG_ULP_TRAP_WAKEUP` Kconfig option is this behavior is not desired.
249+
250+
Heap
251+
----
252+
253+
In previous versions of ESP-IDF, the capability MALLOC_CAP_EXEC would be available regardless of the memory protection configuration state. This implied that a call to e.g., :cpp:func:`heap_caps_malloc` with MALLOC_CAP_EXEC would return NULL when CONFIG_ESP_SYSTEM_MEMPROT_FEATURE or CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT are enabled.
254+
255+
Since ESP-IDF v6.0, the definition of MALLOC_CAP_EXEC is conditional, meaning that if CONFIG_ESP_SYSTEM_MEMPROT is enabled, MALLOC_CAP_EXEC will not be defined. Therefore, using it will generate a compile time error.

0 commit comments

Comments
 (0)