mirror of
https://github.com/espressif/esp-idf.git
synced 2026-08-18 06:35:35 +03:00
fix(sdmmc): Validate DMA buffer address range
Closes https://github.com/espressif/esp-idf/issues/18714
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct sd_host_sdmmc_slot_t sd_host_sdmmc_slot_t;
|
||||
|
||||
bool sd_host_check_buffer_alignment(sd_host_sdmmc_slot_t *slot, const void *buf, size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "esp_check.h"
|
||||
#include "esp_pm.h"
|
||||
#include "esp_cache.h"
|
||||
#include "esp_private/sd_host_buffer.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "driver/sd_host_sdmmc.h"
|
||||
@@ -95,7 +96,6 @@ typedef struct {
|
||||
size_t desc_remaining;
|
||||
} sd_host_sdmmc_trans_state_t;
|
||||
|
||||
typedef struct sd_host_sdmmc_slot_t sd_host_sdmmc_slot_t;
|
||||
typedef struct sd_host_sdmmc_ctlr_t sd_host_sdmmc_ctlr_t;
|
||||
|
||||
/**
|
||||
@@ -333,19 +333,6 @@ void sd_host_dma_prepare(sd_host_sdmmc_slot_t *slot, void* data_ptr, size_t data
|
||||
/*---------------------------------------------------------------
|
||||
Info APIs
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Check SD buffer alignment
|
||||
*
|
||||
* @param[in] slot SD Host slot handle
|
||||
* @param[in] buf Buffer pointer
|
||||
* @param[in] size Buffer size
|
||||
*
|
||||
* @return
|
||||
* - True: alignment requirement is satisfied
|
||||
* - False: alignment requirement is not satisfied
|
||||
*/
|
||||
bool sd_host_check_buffer_alignment(sd_host_sdmmc_slot_t *slot, const void *buf, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Get SD Host slot real frequency
|
||||
*
|
||||
|
||||
@@ -528,6 +528,19 @@ static esp_err_t sd_host_slot_sdmmc_get_info(sd_host_slot_handle_t slot, sd_host
|
||||
/*---------------------------------------------------------------
|
||||
Internal APIs
|
||||
---------------------------------------------------------------*/
|
||||
static bool sdmmc_dma_accessible(const void *ptr)
|
||||
{
|
||||
if (esp_ptr_external_ram(ptr)) {
|
||||
#if SOC_SDMMC_PSRAM_DMA_CAPABLE
|
||||
return esp_ptr_dma_ext_capable(ptr);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
return esp_ptr_dma_capable(ptr);
|
||||
}
|
||||
|
||||
bool sd_host_check_buffer_alignment(sd_host_sdmmc_slot_t *slot, const void *buf, size_t size)
|
||||
{
|
||||
//for future-proof
|
||||
@@ -536,15 +549,17 @@ bool sd_host_check_buffer_alignment(sd_host_sdmmc_slot_t *slot, const void *buf,
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !SOC_SDMMC_PSRAM_DMA_CAPABLE
|
||||
// The SDMMC peripheral's DMA cannot reach PSRAM on this target, so a PSRAM
|
||||
// buffer can never be used directly regardless of its alignment. Reporting
|
||||
// it as not directly usable makes the protocol layer fall back to an
|
||||
// internal DMA-capable buffer.
|
||||
if (esp_ptr_external_ram(buf)) {
|
||||
uintptr_t start = (uintptr_t) buf;
|
||||
if (size - 1 > UINTPTR_MAX - start) {
|
||||
return false;
|
||||
}
|
||||
const void *end = (const void *)(start + size - 1);
|
||||
|
||||
bool not_dma_accessible = !sdmmc_dma_accessible(buf) || !sdmmc_dma_accessible(end);
|
||||
bool different_memory_types = esp_ptr_external_ram(buf) != esp_ptr_external_ram(end);
|
||||
if (not_dma_accessible || different_memory_types) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
int cache_flags = 0;
|
||||
|
||||
@@ -16,6 +16,7 @@ endif()
|
||||
|
||||
set(priv_requires "sdmmc"
|
||||
"esp_driver_sdmmc"
|
||||
"esp_psram"
|
||||
"sdmmc_test_boards"
|
||||
"common_test_flows"
|
||||
"unity"
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include "unity.h"
|
||||
#include "esp_psram.h"
|
||||
#include "sdmmc_cmd.h"
|
||||
#include "sdmmc_test_begin_end_sd.h"
|
||||
#include "sdmmc_test_rw_common.h"
|
||||
@@ -135,6 +136,10 @@ static void do_one_sdmmc_rw_test_psram_dma_buffer(int slot, int width)
|
||||
int freq_khz = SDMMC_FREQ_HIGHSPEED;
|
||||
#if !CONFIG_SPIRAM
|
||||
TEST_IGNORE_MESSAGE("PSRAM is not enabled");
|
||||
#else
|
||||
if (!esp_psram_is_initialized()) {
|
||||
TEST_IGNORE_MESSAGE("PSRAM is not available");
|
||||
}
|
||||
#endif
|
||||
sdmmc_test_sd_skip_if_board_incompatible(slot, width, freq_khz, NO_DDR, NO_EMMC);
|
||||
sdmmc_test_sd_begin(slot, width, freq_khz, 0, &card);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
set(srcs "test_app_main.c" "test_sd_driver_resource.c")
|
||||
set(srcs "test_app_main.c" "test_sd_driver_resource.c" "test_sdmmc_buffer.c")
|
||||
|
||||
set(priv_requires
|
||||
# tests reside in this component, also available for `sdmmc_console`
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "unity.h"
|
||||
#include "esp_private/sd_host_buffer.h"
|
||||
#include "soc/soc.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_memory_utils.h"
|
||||
#include "esp_psram.h"
|
||||
|
||||
#if SOC_RTC_FAST_MEM_SUPPORTED
|
||||
TEST_CASE("SDMMC rejects an RTC fast RAM DMA buffer", "[sdmmc]")
|
||||
{
|
||||
const size_t buffer_size = 512;
|
||||
void *internal_dma_buf = heap_caps_malloc(buffer_size, MALLOC_CAP_DMA | MALLOC_CAP_CACHE_ALIGNED);
|
||||
const size_t offset = 0x20;
|
||||
const void *rtc_fast_ram_buf = (const void *)(SOC_RTC_DRAM_LOW + offset);
|
||||
TEST_ASSERT_NOT_NULL(internal_dma_buf);
|
||||
|
||||
TEST_ASSERT_TRUE(sd_host_check_buffer_alignment(NULL, internal_dma_buf, buffer_size));
|
||||
TEST_ASSERT_FALSE(sd_host_check_buffer_alignment(NULL, rtc_fast_ram_buf, buffer_size));
|
||||
TEST_ASSERT_FALSE(sd_host_check_buffer_alignment(NULL, (const void *)(UINTPTR_MAX - 255), buffer_size));
|
||||
|
||||
heap_caps_free(internal_dma_buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_SPIRAM && !SOC_SDMMC_PSRAM_DMA_CAPABLE
|
||||
TEST_CASE("SDMMC rejects a PSRAM buffer when PSRAM is not DMA capable", "[sdmmc]")
|
||||
{
|
||||
const size_t buffer_size = 512;
|
||||
if (!esp_psram_is_initialized()) {
|
||||
TEST_IGNORE_MESSAGE("PSRAM is not available");
|
||||
}
|
||||
|
||||
void *psram_buf = heap_caps_malloc(buffer_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_CACHE_ALIGNED);
|
||||
TEST_ASSERT_NOT_NULL(psram_buf);
|
||||
TEST_ASSERT_TRUE(esp_ptr_external_ram(psram_buf));
|
||||
|
||||
TEST_ASSERT_FALSE(sd_host_check_buffer_alignment(NULL, psram_buf, buffer_size));
|
||||
|
||||
heap_caps_free(psram_buf);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,2 @@
|
||||
CONFIG_SPIRAM=y
|
||||
CONFIG_SPIRAM_IGNORE_NOTFOUND=y
|
||||
@@ -0,0 +1,2 @@
|
||||
CONFIG_SPIRAM=y
|
||||
CONFIG_SPIRAM_IGNORE_NOTFOUND=y
|
||||
Reference in New Issue
Block a user