aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIoannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>2020-07-30 15:09:01 +0200
committerMáté Tóth-Pál <Mate.Toth-Pal@arm.com>2020-09-14 11:21:05 +0000
commit130248c6ef674334d8ff63878521bf4cf3f76a7f (patch)
tree2bd15391784d1d1cbbb480c68147acaf16d32b61
parent8f895ab86920549747f6d8b33eb710a3da906744 (diff)
downloadtrusted-firmware-m-130248c6ef674334d8ff63878521bf4cf3f76a7f.tar.gz
SPM: make has_access_to_region() compatible with vendor IDAUs
We enhance the implementation of has_access_to_region(), so it works with IDAU implementations, i.e. other than the ARM SAU. We add a hook for a platform-specific check, in case the memory address range crosses multiple IDAU boundaries. We provide a declaration of the platform-specific hook in SPM HAL API. Additional information: The existing implementation of has_access_to_region() is based on the CMSE address range check API for ARMv8-M that works with the Test Target instructions. The address range checks function, however, will not return true (i.e. a passing result for the check, based on the provided flags and the underlying attribution policy), if the memory range being is checked is crossing one or multiple IDAU boundaries, regardless of whether the current attribution policy satisfies the query. This has been identified in Nordic Cortex-M33 platforms, which have an implementation-defined security attribution unit. In order to be able to use the has_access_to_region() function, the implementation has to be enhanced with an additional check, whether the range actually crossed IDAU boundaries. In that case, we add a hook for a platform-specific function that re-checks the access policy taking into account the characteristics of the platform-specific IDAU. The change in has_access_to_region is only compiled in when __SAUREGION_PRESENT is not defined (or defined as 0), so it has no effect on platforms that implement the SAU peripheral. The patch also includes an API definition of a platform-specific function check for access permissions. The patch is required to be able to successfully run TF-M on Nordic nRF platforms. Change-Id: I18ad67637e561a54786846b844adde21240438f1 Signed-off-by: Ioannis Glaropoulos <Ioannis.Glaropoulos@nordicsemi.no>
-rw-r--r--platform/include/tfm_spm_hal.h18
-rw-r--r--secure_fw/spm/common/tfm_core_mem_check.c20
2 files changed, 38 insertions, 0 deletions
diff --git a/platform/include/tfm_spm_hal.h b/platform/include/tfm_spm_hal.h
index 673fbc91b8..3756d9c20d 100644
--- a/platform/include/tfm_spm_hal.h
+++ b/platform/include/tfm_spm_hal.h
@@ -286,4 +286,22 @@ void tfm_spm_hal_get_ns_access_attr(const void *p, size_t s,
#endif /*TFM_MULTI_CORE_TOPOLOGY*/
+#if !defined(__SAUREGION_PRESENT) || (__SAUREGION_PRESENT == 0)
+/**
+ * \brief Platform-specific check whether the current partition has access to a memory range
+ *
+ * The function checks whether the current partition has access to a memory range,
+ * taking into consideration the implementation-defined attribution unit that is
+ * present on a particular platform.
+ *
+ * \param[in] p The start address of the range to check
+ * \param[in] s The size of the range to check
+ * \param[in] flags The flags to pass to the cmse_check_address_range func
+ *
+ * \return True if the access is granted, false otherwise.
+ */
+bool tfm_spm_hal_has_access_to_region(const void *p, size_t s,
+ int flags);
+#endif /* !defined(__SAUREGION_PRESENT) || (__SAUREGION_PRESENT == 0) */
+
#endif /* __TFM_SPM_HAL_H__ */
diff --git a/secure_fw/spm/common/tfm_core_mem_check.c b/secure_fw/spm/common/tfm_core_mem_check.c
index 0514785500..aeb0a86fa0 100644
--- a/secure_fw/spm/common/tfm_core_mem_check.c
+++ b/secure_fw/spm/common/tfm_core_mem_check.c
@@ -9,6 +9,7 @@
#include <stdbool.h>
#include "region_defs.h"
#include "tfm_arch.h"
+#include "tfm_spm_hal.h"
#include "tfm_api.h"
#ifdef TFM_PSA_API
#include "spm_ipc.h"
@@ -41,6 +42,25 @@ static enum tfm_status_e has_access_to_region(const void *p, size_t s,
range_access_allowed_by_mpu =
cmse_check_address_range((void *)p, s, flags) != NULL;
+#if !defined(__SAUREGION_PRESENT) || (__SAUREGION_PRESENT == 0)
+ if (!range_access_allowed_by_mpu) {
+ /*
+ * Verification failure may be due to address range crossing
+ * one or multiple IDAU boundaries. In this case request a
+ * platform-specific check for access permissions.
+ */
+ cmse_address_info_t addr_info_base = cmse_TT((void *)p);
+ cmse_address_info_t addr_info_last = cmse_TT((void *)((uint32_t)p + s - 1));
+
+ if ((addr_info_base.flags.idau_region_valid != 0) &&
+ (addr_info_last.flags.idau_region_valid != 0) &&
+ (addr_info_base.flags.idau_region != addr_info_last.flags.idau_region)) {
+ range_access_allowed_by_mpu =
+ tfm_spm_hal_has_access_to_region(p, s, flags);
+ }
+ }
+#endif
+
if (range_access_allowed_by_mpu) {
return TFM_SUCCESS;
}