Core: refactor error handling scenarios
Secure partition to partition calls are not permitted
while TF-M is initializing. Detect unpermitted function
calls.
Move some distributed request call checks to dedicated
function.
Provide more verbosity in about fault type.
Remove redundant checks.
Change-Id: I56719ebb1d7f4443178ebba9c023ba0ee1c6d0a3
Signed-off-by: Miklos Balint <miklos.balint@arm.com>
diff --git a/app/tfm_integ_test.c b/app/tfm_integ_test.c
index 367847c..b2777da 100644
--- a/app/tfm_integ_test.c
+++ b/app/tfm_integ_test.c
@@ -34,21 +34,10 @@
case TFM_SUCCESS: \
LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") successful!");\
break; \
- case TFM_PARTITION_PENDED: \
- LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") pended!"); \
- break; \
- case TFM_ERROR_PARTITION_ALREADY_PENDED: \
- LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") failed, " \
- "already pended!");\
- break; \
case TFM_ERROR_SECURE_DOMAIN_LOCKED: \
LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") failed, " \
"S domain locked!");\
break; \
- case TFM_ERROR_NS_THREAD_MODE_CALL: \
- LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") failed, " \
- "NS thread mode!");\
- break; \
default: \
LOG_MSG("Secure call to " #fn "(" #__VA_ARGS__") failed, " \
"generic!");\
diff --git a/interface/include/tfm_api.h b/interface/include/tfm_api.h
index efe24e9..fea137a 100644
--- a/interface/include/tfm_api.h
+++ b/interface/include/tfm_api.h
@@ -45,13 +45,13 @@
enum tfm_status_e
{
TFM_SUCCESS = 0,
- TFM_PARTITION_PENDED,
TFM_PARTITION_BUSY,
- TFM_ERROR_PARTITION_ALREADY_PENDED,
TFM_ERROR_SECURE_DOMAIN_LOCKED,
TFM_ERROR_INVALID_PARAMETER,
TFM_ERROR_PARTITION_NON_REENTRANT,
TFM_ERROR_NS_THREAD_MODE_CALL,
+ TFM_ERROR_NOT_INITIALIZED,
+ TFM_ERROR_NO_ACTIVE_PARTITION,
TFM_ERROR_INVALID_EXC_MODE,
TFM_SECURE_LOCK_FAILED,
TFM_SECURE_UNLOCK_FAILED,
diff --git a/secure_fw/core/tfm_secure_api.c b/secure_fw/core/tfm_secure_api.c
index 5491386..8f74047 100644
--- a/secure_fw/core/tfm_secure_api.c
+++ b/secure_fw/core/tfm_secure_api.c
@@ -33,8 +33,6 @@
REGION_DECLARE(Image$$, TFM_SECURE_STACK, $$ZI$$Limit);
#endif
-extern void tfm_core_partition_return_svc(void);
-
/* This is the "Big Lock" on the secure side, to guarantee single entry
* to SPE
*/
@@ -78,10 +76,10 @@
return;
}
-static int32_t tfm_push_lock(struct tfm_sfn_req_s *desc_ptr, uint32_t excReturn)
+static int32_t tfm_start_partition(struct tfm_sfn_req_s *desc_ptr,
+ uint32_t excReturn)
{
- uint32_t caller_partition_idx =
- tfm_spm_partition_get_running_partition_idx();
+ uint32_t caller_partition_idx = desc_ptr->caller_part_idx;
const struct spm_partition_runtime_data_t *curr_part_data;
uint32_t caller_flags;
register uint32_t partition_idx;
@@ -93,11 +91,6 @@
uint32_t caller_partition_id;
int32_t client_id;
- /* Check partition idx validity */
- if (caller_partition_idx == SPM_INVALID_PARTITION_IDX) {
- return TFM_SECURE_LOCK_FAILED;
- }
-
caller_flags = tfm_spm_partition_get_flags(caller_partition_idx);
/* Check partition state consistency */
@@ -125,9 +118,7 @@
caller_partition_id = tfm_spm_partition_get_partition_id(
caller_partition_idx);
- if ((tfm_secure_api_initializing) &&
- (caller_partition_id == TFM_SP_CORE_ID) &&
- (partition_state == SPM_PARTITION_STATE_UNINIT)) {
+ if (tfm_secure_api_initializing) {
#if TFM_LVL != 1
/* Make thread mode unprivileged while untrusted partition init is
* executed
@@ -224,7 +215,7 @@
return TFM_SUCCESS;
}
-static int32_t tfm_pop_lock(uint32_t *excReturn)
+static int32_t tfm_return_from_partition(uint32_t *excReturn)
{
uint32_t current_partition_idx =
tfm_spm_partition_get_running_partition_idx();
@@ -328,8 +319,6 @@
tfm_spm_partition_set_state(current_partition_idx,
SPM_PARTITION_STATE_IDLE);
- tfm_spm_partition_set_caller_partition_idx(current_partition_idx,
- SPM_INVALID_PARTITION_IDX);
tfm_spm_partition_set_state(return_partition_idx,
SPM_PARTITION_STATE_RUNNING);
@@ -358,11 +347,9 @@
static int32_t tfm_core_check_sfn_req_rules(
struct tfm_sfn_req_s *desc_ptr)
{
- if (desc_ptr->exc_num != EXC_NUM_THREAD_MODE) {
- /* Veneer should not be called from handler mode!
- * FixMe: this is potential attack, trigger fault handling
- */
- return TFM_ERROR_INVALID_EXC_MODE;
+ /* Check partition idx validity */
+ if (desc_ptr->caller_part_idx == SPM_INVALID_PARTITION_IDX) {
+ return TFM_ERROR_NO_ACTIVE_PARTITION;
}
if ((desc_ptr->ns_caller) && (tfm_secure_lock != 0)) {
@@ -374,6 +361,17 @@
return TFM_ERROR_SECURE_DOMAIN_LOCKED;
}
+ if (tfm_secure_api_initializing) {
+ int32_t id =
+ tfm_spm_partition_get_partition_id(desc_ptr->caller_part_idx);
+
+ if ((id != TFM_SP_CORE_ID) || (tfm_secure_lock != 0)) {
+ /* Invalid request during system initialization */
+ ERROR_MSG("Invalid service request during initialization!");
+ return TFM_ERROR_NOT_INITIALIZED;
+ }
+ }
+
return TFM_SUCCESS;
}
@@ -395,20 +393,28 @@
res = tfm_check_sfn_req_integrity(desc_ptr);
if (res != TFM_SUCCESS) {
+ ERROR_MSG("Invalid service request!");
return TFM_ERROR_STATUS(res);
}
__disable_irq();
+ desc_ptr->caller_part_idx = tfm_spm_partition_get_running_partition_idx();
+
res = tfm_core_check_sfn_req_rules(desc_ptr);
if (res != TFM_SUCCESS) {
+ /* FixMe: error compartmentalization TBD */
+ tfm_spm_partition_set_state(
+ desc_ptr->caller_part_idx, SPM_PARTITION_STATE_CLOSED);
__enable_irq();
+ ERROR_MSG("Unauthorized service request!");
return TFM_ERROR_STATUS(res);
}
- res = tfm_push_lock(desc_ptr, excReturn);
+ res = tfm_start_partition(desc_ptr, excReturn);
if (res != TFM_SUCCESS) {
/* FixMe: consider possible fault scenarios */
__enable_irq();
+ ERROR_MSG("Failed to process service request!");
return TFM_ERROR_STATUS(res);
}
@@ -423,11 +429,12 @@
int32_t res;
int32_t *args;
int32_t retVal;
+
/* No excReturn value is needed as no exception handling is used */
res = tfm_core_sfn_request_handler(desc_ptr, 0);
if (res != TFM_SUCCESS) {
- return res;
+ tfm_secure_api_error_handler();
}
/* Secure partition to secure partition call in TFM level 1 */
@@ -435,7 +442,7 @@
retVal = desc_ptr->sfn(args[0], args[1], args[2], args[3]);
/* return handler should restore original exc_return value... */
- res = tfm_pop_lock(NULL);
+ res = tfm_return_from_partition(NULL);
if (res == TFM_SUCCESS) {
/* If unlock successful, pass SS return value to caller */
res = retVal;
@@ -695,39 +702,21 @@
struct tfm_exc_stack_t *svc_ctx, uint32_t excReturn)
{
if (!(excReturn & EXC_RETURN_STACK_PROCESS)) {
- /* Partition request SVC called with MSP active.
+ /* Service request SVC called with MSP active.
* Either invalid configuration for Thread mode or SVC called
* from Handler mode, which is not supported.
* FixMe: error severity TBD
*/
- ERROR_MSG("Partition request SVC called with MSP active!");
+ ERROR_MSG("Service request SVC called with MSP active!");
tfm_secure_api_error_handler();
}
struct tfm_sfn_req_s *desc_ptr = (struct tfm_sfn_req_s *)svc_ctx->R0;
- int32_t res = tfm_check_sfn_req_integrity(desc_ptr);
-
- if (res != TFM_SUCCESS) {
- /* The descriptor is incorrectly filled
- * FixMe: error severity TBD
- */
- svc_ctx->LR = (int32_t)tfm_secure_api_error_handler;
- return excReturn;
+ if (tfm_core_sfn_request_handler(desc_ptr, excReturn) != TFM_SUCCESS) {
+ tfm_secure_api_error_handler();
}
- if (desc_ptr->exc_num != EXC_NUM_THREAD_MODE) {
- /* The descriptor is incorrectly filled for SVC handler
- * FixMe: error severity TBD
- */
- svc_ctx->LR = (int32_t)tfm_secure_api_error_handler;
- return excReturn;
- } else {
- if (tfm_core_sfn_request_handler(desc_ptr, excReturn) != TFM_SUCCESS) {
- svc_ctx->LR = (int32_t)tfm_secure_api_error_handler;
- return excReturn;
- }
- }
return EXC_RETURN_SECURE_FUNCTION;
}
@@ -737,23 +726,14 @@
int32_t res;
if (!(lr & EXC_RETURN_STACK_PROCESS)) {
- /* Partition request SVC called with MSP active.
- * Either invalid configuration for Thread mode or SVC called
- * from Handler mode, which is not supported.
- * FixMe: error severity TBD
- */
- ERROR_MSG("Partition request SVC called with MSP active!");
- tfm_secure_api_error_handler();
- }
-
- /* Store return value from secure partition */
- if (!(lr & EXC_RETURN_STACK_PROCESS)) {
/* Partition return SVC called with MSP active.
* This should not happen!
*/
ERROR_MSG("Partition return SVC called with MSP active!");
tfm_secure_api_error_handler();
}
+
+ /* Store return value from secure partition */
int32_t retVal = *(int32_t *)__get_PSP();
if ((retVal > TFM_SUCCESS) &&
@@ -769,7 +749,7 @@
tfm_secure_api_error_handler();
}
- res = tfm_pop_lock(&lr);
+ res = tfm_return_from_partition(&lr);
if (res != TFM_SUCCESS) {
/* Unlock errors indicate ctx database corruption or unknown anomalies
* Halt execution
diff --git a/secure_fw/core/tfm_secure_api.h b/secure_fw/core/tfm_secure_api.h
index 25e76f8..8fb94c7 100644
--- a/secure_fw/core/tfm_secure_api.h
+++ b/secure_fw/core/tfm_secure_api.h
@@ -30,10 +30,8 @@
#endif
#ifndef TFM_LVL
-#ifndef __DOMAIN_NS
#error TFM_LVL is not defined!
#endif
-#endif
extern void tfm_secure_api_error_handler(void);
@@ -43,7 +41,7 @@
uint32_t sp_id;
sfn_t sfn;
int32_t *args;
- uint32_t exc_num;
+ uint32_t caller_part_idx;
int32_t ns_caller : 1;
};
@@ -97,8 +95,8 @@
desc.sfn = fn;
desc.args = args;
desc.ns_caller = cmse_nonsecure_caller();
- desc.exc_num = __get_active_exc_num();
- if (desc.exc_num != EXC_NUM_THREAD_MODE) {
+ if (__get_active_exc_num() != EXC_NUM_THREAD_MODE) {
+ /* FixMe: Error severity TBD */
return TFM_ERROR_GENERIC;
} else {
#if TFM_LVL == 1
diff --git a/secure_fw/spm/spm_api.c b/secure_fw/spm/spm_api.c
index 77bf5be..83d4414 100644
--- a/secure_fw/spm/spm_api.c
+++ b/secure_fw/spm/spm_api.c
@@ -147,7 +147,6 @@
int32_t res;
desc.args = args;
- desc.exc_num = EXC_NUM_THREAD_MODE;
desc.ns_caller = 0;
desc.sfn = (sfn_t)part->static_data.partition_init;
desc.sp_id = part->static_data.partition_id;