fix(esp_tee): enforce MMU-map vaddr validity at the REE->TEE boundary

This commit is contained in:
Ashish Sharma
2026-07-17 18:14:37 +05:30
committed by Laukik Hase
parent c146cb5322
commit 2fcdb164a1
3 changed files with 58 additions and 7 deletions
@@ -8,6 +8,7 @@
#include "esp_err.h" #include "esp_err.h"
#include "esp_log.h" #include "esp_log.h"
#include "esp_macros.h"
#include "esp_fault.h" #include "esp_fault.h"
#include "hal/mmu_types.h" #include "hal/mmu_types.h"
@@ -38,6 +39,9 @@
static __attribute__((unused)) const char *TAG = "esp_tee_sec_srv_iram"; static __attribute__((unused)) const char *TAG = "esp_tee_sec_srv_iram";
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
#define ALIGN_DOWN(num, align) ((num) & ~((align) - 1))
/* ---------------------------------------------- Interrupts ------------------------------------------------- */ /* ---------------------------------------------- Interrupts ------------------------------------------------- */
#if SOC_INT_CLIC_SUPPORTED #if SOC_INT_CLIC_SUPPORTED
@@ -274,11 +278,37 @@ esp_err_t _ss_esp_tee_sec_storage_ecdsa_sign_pbkdf2(const esp_tee_sec_storage_pb
/* ---------------------------------------------- MMU HAL ------------------------------------------------- */ /* ---------------------------------------------- MMU HAL ------------------------------------------------- */
/* Gates for REE-supplied external-flash address ranges. The HAL maps whole pages,
* so validate the page-rounded span it will actually touch (not the raw byte len)
* and require page-aligned addresses, so a sub-page or misaligned request cannot
* smuggle in an adjacent TEE page. mmu_hal_check_valid_ext_vaddr_region() must be
* enforced HERE, at the boundary: it rejects out-of-window (aliased) vaddrs. */
static bool tee_ree_ext_vaddr_ok(uint32_t mmu_id, uint32_t vaddr, uint32_t len)
{
uint32_t page = mmu_hal_pages_to_bytes(mmu_id, 1);
uint32_t map_len = ALIGN_UP(len, page);
return (len != 0 && map_len >= len && (vaddr % page == 0) &&
mmu_hal_check_valid_ext_vaddr_region(mmu_id, vaddr, map_len,
MMU_VADDR_DATA | MMU_VADDR_INSTRUCTION) &&
!esp_tee_flash_check_vrange_in_tee_region(vaddr, map_len));
}
static bool tee_ree_ext_paddr_ok(uint32_t mmu_id, uint32_t paddr, uint32_t len)
{
uint32_t page = mmu_hal_pages_to_bytes(mmu_id, 1);
uint32_t map_len = ALIGN_UP(len, page);
return (len != 0 && map_len >= len && (paddr % page == 0) &&
mmu_hal_check_valid_paddr_region(mmu_id, paddr, map_len) &&
!esp_tee_flash_check_prange_in_tee_region(paddr, map_len));
}
void _ss_mmu_hal_map_region(uint32_t mmu_id, mmu_target_t mem_type, uint32_t vaddr, void _ss_mmu_hal_map_region(uint32_t mmu_id, mmu_target_t mem_type, uint32_t vaddr,
uint32_t paddr, uint32_t len, uint32_t *out_len) uint32_t paddr, uint32_t len, uint32_t *out_len)
{ {
bool valid_addr = (!esp_tee_flash_check_vrange_in_tee_region(vaddr, len) && bool valid_addr = (tee_ree_ext_vaddr_ok(mmu_id, vaddr, len) &&
!esp_tee_flash_check_prange_in_tee_region(paddr, len) && tee_ree_ext_paddr_ok(mmu_id, paddr, len) &&
esp_tee_buf_in_ree(out_len, sizeof(uint32_t))); esp_tee_buf_in_ree(out_len, sizeof(uint32_t)));
if (!valid_addr) { if (!valid_addr) {
@@ -292,20 +322,23 @@ void _ss_mmu_hal_map_region(uint32_t mmu_id, mmu_target_t mem_type, uint32_t vad
void _ss_mmu_hal_unmap_region(uint32_t mmu_id, uint32_t vaddr, uint32_t len) void _ss_mmu_hal_unmap_region(uint32_t mmu_id, uint32_t vaddr, uint32_t len)
{ {
bool vaddr_chk = esp_tee_flash_check_vrange_in_tee_region(vaddr, len); bool valid_addr = tee_ree_ext_vaddr_ok(mmu_id, vaddr, len);
if (vaddr_chk) { if (!valid_addr) {
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, vaddr); ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, vaddr);
return; return;
} }
ESP_FAULT_ASSERT(!vaddr_chk); ESP_FAULT_ASSERT(valid_addr);
mmu_hal_unmap_region(mmu_id, vaddr, len); mmu_hal_unmap_region(mmu_id, vaddr, len);
} }
bool _ss_mmu_hal_vaddr_to_paddr(uint32_t mmu_id, uint32_t vaddr, uint32_t *out_paddr, mmu_target_t *out_target) bool _ss_mmu_hal_vaddr_to_paddr(uint32_t mmu_id, uint32_t vaddr, uint32_t *out_paddr, mmu_target_t *out_target)
{ {
bool valid_addr = (!esp_tee_flash_check_vaddr_in_tee_region(vaddr) && /* Same aliasing gate as map/unmap; translation itself is page-granular and
* vaddr need not be aligned, so validate the page containing it. */
uint32_t page = mmu_hal_pages_to_bytes(mmu_id, 1);
bool valid_addr = (tee_ree_ext_vaddr_ok(mmu_id, ALIGN_DOWN(vaddr, page), 1) &&
esp_tee_buf_in_ree(out_paddr, sizeof(uint32_t)) && esp_tee_buf_in_ree(out_paddr, sizeof(uint32_t)) &&
esp_tee_buf_in_ree(out_target, sizeof(mmu_target_t))); esp_tee_buf_in_ree(out_target, sizeof(mmu_target_t)));
@@ -319,7 +352,8 @@ bool _ss_mmu_hal_vaddr_to_paddr(uint32_t mmu_id, uint32_t vaddr, uint32_t *out_p
bool _ss_mmu_hal_paddr_to_vaddr(uint32_t mmu_id, uint32_t paddr, mmu_target_t target, mmu_vaddr_t type, uint32_t *out_vaddr) bool _ss_mmu_hal_paddr_to_vaddr(uint32_t mmu_id, uint32_t paddr, mmu_target_t target, mmu_vaddr_t type, uint32_t *out_vaddr)
{ {
bool valid_addr = (!esp_tee_flash_check_paddr_in_tee_region(paddr) && bool valid_addr = (mmu_hal_check_valid_paddr_region(mmu_id, paddr, 1) &&
!esp_tee_flash_check_paddr_in_tee_region(paddr) &&
esp_tee_buf_in_ree(out_vaddr, sizeof(uint32_t))); esp_tee_buf_in_ree(out_vaddr, sizeof(uint32_t)));
if (!valid_addr) { if (!valid_addr) {
+12
View File
@@ -149,6 +149,18 @@ bool mmu_hal_paddr_to_vaddr(uint32_t mmu_id, uint32_t paddr, mmu_target_t target
*/ */
bool mmu_hal_check_valid_ext_vaddr_region(uint32_t mmu_id, uint32_t vaddr_start, uint32_t len, mmu_vaddr_t type); bool mmu_hal_check_valid_ext_vaddr_region(uint32_t mmu_id, uint32_t vaddr_start, uint32_t len, mmu_vaddr_t type);
/**
* Check if the paddr region is valid
*
* @param mmu_id MMU ID
* @param paddr_start start of the physical address
* @param len length, in bytes
*
* @return
* True for valid
*/
bool mmu_hal_check_valid_paddr_region(uint32_t mmu_id, uint32_t paddr_start, uint32_t len);
#if SOC_MMU_PER_EXT_MEM_TARGET #if SOC_MMU_PER_EXT_MEM_TARGET
/** /**
* Get MMU ID from MMU target * Get MMU ID from MMU target
+5
View File
@@ -197,6 +197,11 @@ bool mmu_hal_check_valid_ext_vaddr_region(uint32_t mmu_id, uint32_t vaddr_start,
return mmu_ll_check_valid_ext_vaddr_region(mmu_id, vaddr_start, len, type); return mmu_ll_check_valid_ext_vaddr_region(mmu_id, vaddr_start, len, type);
} }
bool mmu_hal_check_valid_paddr_region(uint32_t mmu_id, uint32_t paddr_start, uint32_t len)
{
return mmu_ll_check_valid_paddr_region(mmu_id, paddr_start, len);
}
#if SOC_MMU_PER_EXT_MEM_TARGET #if SOC_MMU_PER_EXT_MEM_TARGET
uint32_t mmu_hal_get_id_from_target(mmu_target_t target) uint32_t mmu_hal_get_id_from_target(mmu_target_t target)
{ {