summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHarrison Mutai <harrison.mutai@arm.com>2026-06-29 08:47:00 +0000
committerTrustedFirmware Code Review <review@review.trustedfirmware.org>2026-06-29 08:47:00 +0000
commit31255dd9b2e14c1ebe4eab1b8f4984cde72c51d5 (patch)
treec36960f8bf634abdf14c04c56c257e5923250fae
parent0ff6f48335d66e69cfdc42bb9c4d49a43b819bfc (diff)
parenta06d0c222e6b4f78f6b2798372959f9079c76f5c (diff)
downloadarm-trusted-firmware-31255dd9b2e14c1ebe4eab1b8f4984cde72c51d5.tar.gz
arm-trusted-firmware-31255dd9b2e14c1ebe4eab1b8f4984cde72c51d5.zip
Merge "fix(imx8m): validate NS pointer arguments in HAB report handlers" into integration
-rw-r--r--plat/imx/imx8m/imx8m_smc_validation.c42
-rw-r--r--plat/imx/imx8m/imx8mm/platform.mk1
-rw-r--r--plat/imx/imx8m/imx8mn/platform.mk1
-rw-r--r--plat/imx/imx8m/imx8mp/platform.mk1
-rw-r--r--plat/imx/imx8m/imx8mq/platform.mk1
-rw-r--r--plat/imx/imx8m/imx_hab.c68
6 files changed, 109 insertions, 5 deletions
diff --git a/plat/imx/imx8m/imx8m_smc_validation.c b/plat/imx/imx8m/imx8m_smc_validation.c
new file mode 100644
index 000000000..5efe33250
--- /dev/null
+++ b/plat/imx/imx8m/imx8m_smc_validation.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2026 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <common/smc_validation_framework.h>
+
+#include <platform_def.h>
+
+/*
+ * plat_is_valid_ns_address_range() - i.MX8M override.
+ *
+ * Accept only the DRAM region as valid Non-Secure memory, excluding the
+ * BL32 (OP-TEE) carve-out. This prevents NS callers from passing
+ * pointers into OCRAM (BL31), ROM, MMIO, or secure BL32 memory
+ * regions through SMC arguments.
+ */
+bool plat_is_valid_ns_address_range(uintptr_t base, size_t size)
+{
+ uintptr_t end = base + size;
+
+ /* Reject addresses outside DRAM */
+ if ((base < IMX_DRAM_BASE) ||
+ (end > ((uintptr_t)IMX_DRAM_BASE + IMX_DRAM_SIZE))) {
+ return false;
+ }
+
+#if defined(BL32_BASE) && defined(BL32_SIZE)
+ /* Reject addresses that overlap the BL32 (OP-TEE) region */
+ if ((end > BL32_BASE) &&
+ (base < (BL32_BASE + BL32_SIZE))) {
+ return false;
+ }
+#endif
+
+ return true;
+}
diff --git a/plat/imx/imx8m/imx8mm/platform.mk b/plat/imx/imx8m/imx8mm/platform.mk
index f494e47b8..4cad97697 100644
--- a/plat/imx/imx8m/imx8mm/platform.mk
+++ b/plat/imx/imx8m/imx8mm/platform.mk
@@ -34,6 +34,7 @@ BL31_SOURCES += common/desc_image_load.c \
plat/imx/common/imx8_helpers.S \
plat/imx/imx8m/gpc_common.c \
plat/imx/imx8m/imx_hab.c \
+ plat/imx/imx8m/imx8m_smc_validation.c \
plat/imx/imx8m/imx_aipstz.c \
plat/imx/imx8m/imx_rdc.c \
plat/imx/imx8m/imx8m_csu.c \
diff --git a/plat/imx/imx8m/imx8mn/platform.mk b/plat/imx/imx8m/imx8mn/platform.mk
index 6a9d22e12..9cf5b05a6 100644
--- a/plat/imx/imx8m/imx8mn/platform.mk
+++ b/plat/imx/imx8m/imx8mn/platform.mk
@@ -29,6 +29,7 @@ BL31_SOURCES += common/desc_image_load.c \
plat/imx/common/imx8_helpers.S \
plat/imx/imx8m/gpc_common.c \
plat/imx/imx8m/imx_hab.c \
+ plat/imx/imx8m/imx8m_smc_validation.c \
plat/imx/imx8m/imx_aipstz.c \
plat/imx/imx8m/imx_rdc.c \
plat/imx/imx8m/imx8m_caam.c \
diff --git a/plat/imx/imx8m/imx8mp/platform.mk b/plat/imx/imx8m/imx8mp/platform.mk
index 11fc01b0b..7ec417f63 100644
--- a/plat/imx/imx8m/imx8mp/platform.mk
+++ b/plat/imx/imx8m/imx8mp/platform.mk
@@ -31,6 +31,7 @@ BL31_SOURCES += common/desc_image_load.c \
plat/imx/common/imx8_helpers.S \
plat/imx/imx8m/gpc_common.c \
plat/imx/imx8m/imx_hab.c \
+ plat/imx/imx8m/imx8m_smc_validation.c \
plat/imx/imx8m/imx_aipstz.c \
plat/imx/imx8m/imx_rdc.c \
plat/imx/imx8m/imx8m_caam.c \
diff --git a/plat/imx/imx8m/imx8mq/platform.mk b/plat/imx/imx8m/imx8mq/platform.mk
index 76fc07107..17437da04 100644
--- a/plat/imx/imx8m/imx8mq/platform.mk
+++ b/plat/imx/imx8m/imx8mq/platform.mk
@@ -30,6 +30,7 @@ BL31_SOURCES += plat/imx/common/imx8_helpers.S \
plat/imx/imx8m/imx8mq/imx8mq_psci.c \
plat/imx/imx8m/gpc_common.c \
plat/imx/imx8m/imx_hab.c \
+ plat/imx/imx8m/imx8m_smc_validation.c \
plat/imx/imx8m/imx_aipstz.c \
plat/imx/imx8m/imx8m_caam.c \
plat/imx/imx8m/imx8m_ccm.c \
diff --git a/plat/imx/imx8m/imx_hab.c b/plat/imx/imx8m/imx_hab.c
index 222046fb9..d34d495bf 100644
--- a/plat/imx/imx8m/imx_hab.c
+++ b/plat/imx/imx8m/imx_hab.c
@@ -5,7 +5,10 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <common/debug.h>
#include <common/runtime_svc.h>
+#include <common/smc_validation_framework.h>
+
#include <imx_sip_svc.h>
#define HAB_CID_ATF U(2) /* TF-A Caller ID */
@@ -80,7 +83,8 @@ struct hab_rvt_api {
size_t *bytes, hab_loader_callback_f_t loader, uint32_t srkmask, int skip_dcd);
};
-struct hab_rvt_api *g_hab_rvt_api = (struct hab_rvt_api *)HAB_RVT_BASE;
+static const struct hab_rvt_api *g_hab_rvt_api =
+ (const struct hab_rvt_api *)HAB_RVT_BASE;
/*******************************************************************************
* Handler for servicing HAB SMC calls
@@ -102,12 +106,66 @@ int imx_hab_handler(uint32_t smc_fid,
case IMX_SIP_HAB_AUTH_IMG:
return (unsigned long)g_hab_rvt_api->authenticate_image(HAB_CID_ATF,
x2, (void **)x3, (size_t *)x4, NULL);
+
case IMX_SIP_HAB_REPORT_EVENT:
- return g_hab_rvt_api->report_event(HAB_FAILURE,
- (uint32_t)x2, (uint8_t *)x3, (size_t *)x4);
+ {
+ uintptr_t event_buf = (uintptr_t)x3;
+ uintptr_t bytes_ptr = (uintptr_t)x4;
+
+ if (smc_validate_mem_range(bytes_ptr, sizeof(size_t)) != SMC_OK) {
+ WARN("HAB: REPORT_EVENT bytes_ptr 0x%lx failed NS check\n",
+ bytes_ptr);
+ return (int)HAB_FAILURE;
+ }
+
+ size_t max_bytes = *(size_t *)bytes_ptr;
+
+ if (smc_validate_mem_range(event_buf, max_bytes) != SMC_OK) {
+ WARN("HAB: REPORT_EVENT buf 0x%lx+0x%zx failed NS check\n",
+ event_buf, max_bytes);
+ return (int)HAB_FAILURE;
+ }
+
+ enum hab_status status = g_hab_rvt_api->report_event(
+ HAB_FAILURE, (uint32_t)x2,
+ (uint8_t *)event_buf, &max_bytes);
+
+ *(size_t *)bytes_ptr = max_bytes;
+
+ return (int)status;
+ }
+
case IMX_SIP_HAB_REPORT_STATUS:
- return g_hab_rvt_api->report_status((enum hab_config *)x2,
- (enum hab_state *)x3);
+ {
+ uintptr_t config_ptr = (uintptr_t)x2;
+ uintptr_t state_ptr = (uintptr_t)x3;
+
+ if (smc_validate_mem_range(config_ptr,
+ sizeof(enum hab_config)) != SMC_OK) {
+ WARN("HAB: REPORT_STATUS config_ptr 0x%lx failed NS check\n",
+ config_ptr);
+ return (int)HAB_FAILURE;
+ }
+
+ if (smc_validate_mem_range(state_ptr,
+ sizeof(enum hab_state)) != SMC_OK) {
+ WARN("HAB: REPORT_STATUS state_ptr 0x%lx failed NS check\n",
+ state_ptr);
+ return (int)HAB_FAILURE;
+ }
+
+ enum hab_config config_local;
+ enum hab_state state_local;
+
+ enum hab_status status = g_hab_rvt_api->report_status(
+ &config_local, &state_local);
+
+ *(enum hab_config *)config_ptr = config_local;
+ *(enum hab_state *)state_ptr = state_local;
+
+ return (int)status;
+ }
+
case IMX_SIP_HAB_FAILSAFE:
g_hab_rvt_api->failsafe();
break;