Stack_seal_mitigation: Secure harden the Main Stack Pointer (MSP)
Seal the MSP_S for both IPC mode and Library mode with the recommended
stack seal value during runtime. Check the comments in the header
file for more details.
Change-Id: Icc36f318d5416aa2c3df8b4d647d892caddd20c3
Signed-off-by: Ken Liu <ken.liu@arm.com>
diff --git a/secure_fw/spm/cmsis_func/main.c b/secure_fw/spm/cmsis_func/main.c
index f22dfbf..920d0f5 100644
--- a/secure_fw/spm/cmsis_func/main.c
+++ b/secure_fw/spm/cmsis_func/main.c
@@ -120,8 +120,9 @@
int main(void)
{
/* set Main Stack Pointer limit */
- tfm_arch_set_msplim((uint32_t)®ION_NAME(Image$$, ARM_LIB_STACK_MSP,
- $$ZI$$Base));
+ tfm_arch_init_secure_msp((uint32_t)®ION_NAME(Image$$,
+ ARM_LIB_STACK_MSP,
+ $$ZI$$Base));
if (tfm_core_init() != TFM_SUCCESS) {
tfm_core_panic();
diff --git a/secure_fw/spm/cmsis_psa/arch/tfm_arch_v6m_v7m.h b/secure_fw/spm/cmsis_psa/arch/tfm_arch_v6m_v7m.h
index 380df16..77d7806 100644
--- a/secure_fw/spm/cmsis_psa/arch/tfm_arch_v6m_v7m.h
+++ b/secure_fw/spm/cmsis_psa/arch/tfm_arch_v6m_v7m.h
@@ -107,11 +107,11 @@
}
/**
- * \brief Set MSP limit value.
+ * \brief Secure the MSP
*
* \param[in] msplim MSP limit value to be written.
*/
-__STATIC_INLINE void tfm_arch_set_msplim(uint32_t msplim)
+__STATIC_INLINE void tfm_arch_init_secure_msp(uint32_t msplim)
{
/*
* Defined as an empty function now.
diff --git a/secure_fw/spm/cmsis_psa/main.c b/secure_fw/spm/cmsis_psa/main.c
index 5bea871..6ddec00 100644
--- a/secure_fw/spm/cmsis_psa/main.c
+++ b/secure_fw/spm/cmsis_psa/main.c
@@ -119,7 +119,7 @@
int main(void)
{
/* set Main Stack Pointer limit */
- tfm_arch_set_msplim((uint32_t)®ION_NAME(Image$$, ARM_LIB_STACK_MSP,
+ tfm_arch_init_secure_msp((uint32_t)®ION_NAME(Image$$, ARM_LIB_STACK_MSP,
$$ZI$$Base));
if (tfm_core_init() != TFM_SUCCESS) {
diff --git a/secure_fw/spm/cmsis_psa/spm_ipc.c b/secure_fw/spm/cmsis_psa/spm_ipc.c
index 66626c9..deebf3d 100644
--- a/secure_fw/spm/cmsis_psa/spm_ipc.c
+++ b/secure_fw/spm/cmsis_psa/spm_ipc.c
@@ -941,7 +941,7 @@
*/
stacked_ctx_pos = (uintptr_t)p_ctx +
sizeof(struct tfm_state_context_t) +
- TFM_VENEER_STACK_GUARD_SIZE;
+ TFM_STACK_SEALED_SIZE;
if (is_stack_alloc_fp_space(exc_return)) {
#if defined (__FPU_USED) && (__FPU_USED == 1U)
diff --git a/secure_fw/spm/include/tfm_arch_v8m.h b/secure_fw/spm/include/tfm_arch_v8m.h
index 94a2e4f..a0912c4 100644
--- a/secure_fw/spm/include/tfm_arch_v8m.h
+++ b/secure_fw/spm/include/tfm_arch_v8m.h
@@ -11,6 +11,8 @@
#include <stdbool.h>
#include "cmsis_compiler.h"
+#include "tfm_core_trustzone.h"
+#include "utilities.h"
#define EXC_RETURN_INDICATOR (0xFF << 24)
#define EXC_RETURN_RES1 (0x1FFFF << 7)
@@ -119,12 +121,29 @@
}
/**
- * \brief Set MSPLIM register.
+ * \brief Set MSPLIM register and seal the MSP.
+ *
+ * This function assumes that the caller is using PSP when calling this
+ * function.
*
* \param[in] msplim Register value to be written into MSPLIM.
*/
-__STATIC_INLINE void tfm_arch_set_msplim(uint32_t msplim)
+__STATIC_INLINE void tfm_arch_init_secure_msp(uint32_t msplim)
{
+ uint32_t mstk_adr = __get_MSP();
+
+ /*
+ * Seal the main stack and update MSP to point below the stack seal.
+ * Set MSPLIM. As the initial 'main()' code is running under privileged PSP
+ * manipulating MSP works here.
+ */
+ TFM_CORE_ASSERT((mstk_adr & 0x7) == 0);
+ mstk_adr -= TFM_STACK_SEALED_SIZE;
+
+ *((uint32_t *)mstk_adr) = TFM_STACK_SEAL_VALUE;
+ *((uint32_t *)(mstk_adr + 4)) = TFM_STACK_SEAL_VALUE;
+
+ __set_MSP(mstk_adr);
__set_MSPLIM(msplim);
}
diff --git a/secure_fw/spm/include/tfm_core_trustzone.h b/secure_fw/spm/include/tfm_core_trustzone.h
index 061235e..c53e034 100644
--- a/secure_fw/spm/include/tfm_core_trustzone.h
+++ b/secure_fw/spm/include/tfm_core_trustzone.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -11,13 +11,13 @@
/* This file holds specification or design defined TrustZone settings. */
/*
- * The non-secure entry stack guard words. To avoid fuzzing jump to
- * FNC_RETURN in NSPE, the non-secure entry address is stacked into
- * bottom (high end address) of secure stack. This would lead the
- * fuzzing jump of FNC_RETURN to the non-secure entry. Define a size
- * here for code reference.
+ * To avoid faking jump with FNC_RETURN or EXC_RETURN in NSPE, seal the secure
+ * stack by putting two words (8 bytes) at the start of stack (higher address)
+ * of it. The Armv8-M Architecture Reference Manual recommends to use seal value
+ * 0xFEF5EDA5.
*/
-#define TFM_VENEER_STACK_GUARD_SIZE 8
+#define TFM_STACK_SEALED_SIZE 8
+#define TFM_STACK_SEAL_VALUE 0xFEF5EDA5
/*
* The numbers in 32bit words while basic FP involved in preempted context: