Core: Support isolation 2 memory check
In isolation level 2, the secure partition is divided
into two modes: privileged mode or unprivileged mode.
Add privileged setting check while performing memory
check.
Change-Id: I3a23df9aea34920f662a36e1389063d591b37119
Signed-off-by: Summer Qin <summer.qin@arm.com>
diff --git a/secure_fw/core/ipc/include/tfm_spm.h b/secure_fw/core/ipc/include/tfm_spm.h
index 62adf34..83c5172 100644
--- a/secure_fw/core/ipc/include/tfm_spm.h
+++ b/secure_fw/core/ipc/include/tfm_spm.h
@@ -71,6 +71,16 @@
*/
uint32_t tfm_spm_partition_get_running_partition_id_ext(void);
+/**
+ * \brief Get the current partition mode.
+ *
+ * \param[in] partition_idx Index of current partition
+ *
+ * \retval TFM_PARTITION_PRIVILEGED_MODE Privileged mode
+ * \retval TFM_PARTITION_UNPRIVILEGED_MODE Unprivileged mode
+ */
+uint32_t tfm_spm_partition_get_privileged_mode(uint32_t partition_idx);
+
/******************** Service handle management functions ********************/
/**
@@ -275,20 +285,24 @@
uint32_t minor_version);
/**
- * \brief Check the memory reference is valid.
+ * \brief Check the memory reference is valid.
*
- * \param[in] buffer Pointer of memory reference
- * \param[in] len Length of memory reference in bytes
- * \param[in] ns_caller From non-secure caller
- * \param[in] access Type of access specified by the
- * \ref tfm_memory_access_e
+ * \param[in] buffer Pointer of memory reference
+ * \param[in] len Length of memory reference in bytes
+ * \param[in] ns_caller From non-secure caller
+ * \param[in] access Type of access specified by the
+ * \ref tfm_memory_access_e
+ * \param[in] privileged Privileged mode or unprivileged mode:
+ * \ref TFM_PARTITION_UNPRIVILEGED_MODE
+ * \ref TFM_PARTITION_PRIVILEGED_MODE
*
- * \retval IPC_SUCCESS Success
- * \retval IPC_ERROR_BAD_PARAMETERS Bad parameters input
- * \retval IPC_ERROR_MEMORY_CHECK Check failed
+ * \retval IPC_SUCCESS Success
+ * \retval IPC_ERROR_BAD_PARAMETERS Bad parameters input
+ * \retval IPC_ERROR_MEMORY_CHECK Check failed
*/
int32_t tfm_memory_check(void *buffer, size_t len, int32_t ns_caller,
- enum tfm_memory_access_e access);
+ enum tfm_memory_access_e access,
+ uint32_t privileged);
/* This function should be called before schedule function */
void tfm_spm_init(void);
diff --git a/secure_fw/core/ipc/tfm_spm.c b/secure_fw/core/ipc/tfm_spm.c
index 50aa249..1ecc1a4 100644
--- a/secure_fw/core/ipc/tfm_spm.c
+++ b/secure_fw/core/ipc/tfm_spm.c
@@ -455,9 +455,9 @@
partition_priority;
}
-/* FixMe: This is only valid for TFM LVL 1 now */
int32_t tfm_memory_check(void *buffer, size_t len, int32_t ns_caller,
- enum tfm_memory_access_e access)
+ enum tfm_memory_access_e access,
+ uint32_t privileged)
{
int32_t err;
@@ -475,9 +475,11 @@
}
if (access == TFM_MEMORY_ACCESS_RW) {
- err = tfm_core_has_write_access_to_region(buffer, len, ns_caller);
+ err = tfm_core_has_write_access_to_region(buffer, len, ns_caller,
+ privileged);
} else {
- err = tfm_core_has_read_access_to_region(buffer, len, ns_caller);
+ err = tfm_core_has_read_access_to_region(buffer, len, ns_caller,
+ privileged);
}
if (err == TFM_SUCCESS) {
return IPC_SUCCESS;
@@ -486,6 +488,15 @@
return IPC_ERROR_MEMORY_CHECK;
}
+uint32_t tfm_spm_partition_get_privileged_mode(uint32_t partition_idx)
+{
+ if (tfm_spm_partition_get_flags(partition_idx) & SPM_PART_FLAG_PSA_ROT) {
+ return TFM_PARTITION_PRIVILEGED_MODE;
+ } else {
+ return TFM_PARTITION_UNPRIVILEGED_MODE;
+ }
+}
+
/********************** SPM functions for thread mode ************************/
void tfm_spm_init(void)
diff --git a/secure_fw/core/ipc/tfm_svcalls.c b/secure_fw/core/ipc/tfm_svcalls.c
index 29f9130..49b009f 100644
--- a/secure_fw/core/ipc/tfm_svcalls.c
+++ b/secure_fw/core/ipc/tfm_svcalls.c
@@ -21,6 +21,7 @@
#include "tfm_api.h"
#include "tfm_secure_api.h"
#include "tfm_memory_utils.h"
+#include "spm_api.h"
#define PSA_TIMEOUT_MASK PSA_BLOCK
@@ -116,9 +117,18 @@
struct tfm_spm_service_t *service;
struct tfm_msg_body_t *msg;
int i;
+ struct tfm_spm_ipc_partition_t *partition = NULL;
+ uint32_t privileged;
TFM_ASSERT(args != NULL);
handle = (psa_handle_t)args[0];
+
+ partition = tfm_spm_get_running_partition();
+ if (!partition) {
+ tfm_panic();
+ }
+ privileged = tfm_spm_partition_get_privileged_mode(partition->index);
+
if (!ns_caller) {
inptr = (psa_invec *)args[1];
in_num = (size_t)args[2];
@@ -153,11 +163,11 @@
* memory reference for buffer is invalid or not readable.
*/
if (tfm_memory_check((void *)args[1], sizeof(uint32_t),
- ns_caller, TFM_MEMORY_ACCESS_RO) != IPC_SUCCESS) {
+ ns_caller, TFM_MEMORY_ACCESS_RO, privileged) != IPC_SUCCESS) {
tfm_panic();
}
if (tfm_memory_check((void *)args[2], sizeof(uint32_t),
- ns_caller, TFM_MEMORY_ACCESS_RO) != IPC_SUCCESS) {
+ ns_caller, TFM_MEMORY_ACCESS_RO, privileged) != IPC_SUCCESS) {
tfm_panic();
}
@@ -185,7 +195,7 @@
* readable.
*/
if (tfm_memory_check((void *)inptr, in_num * sizeof(psa_invec),
- ns_caller, TFM_MEMORY_ACCESS_RO) != IPC_SUCCESS) {
+ ns_caller, TFM_MEMORY_ACCESS_RO, privileged) != IPC_SUCCESS) {
tfm_panic();
}
/*
@@ -194,7 +204,7 @@
* the wrap output vector is invalid or not read-write.
*/
if (tfm_memory_check((void *)outptr, out_num * sizeof(psa_outvec),
- ns_caller, TFM_MEMORY_ACCESS_RW) != IPC_SUCCESS) {
+ ns_caller, TFM_MEMORY_ACCESS_RW, privileged) != IPC_SUCCESS) {
tfm_panic();
}
@@ -211,7 +221,7 @@
*/
for (i = 0; i < in_num; i++) {
if (tfm_memory_check((void *)invecs[i].base, invecs[i].len,
- ns_caller, TFM_MEMORY_ACCESS_RO) != IPC_SUCCESS) {
+ ns_caller, TFM_MEMORY_ACCESS_RO, privileged) != IPC_SUCCESS) {
tfm_panic();
}
}
@@ -221,7 +231,7 @@
*/
for (i = 0; i < out_num; i++) {
if (tfm_memory_check(outvecs[i].base, outvecs[i].len,
- ns_caller, TFM_MEMORY_ACCESS_RW) != IPC_SUCCESS) {
+ ns_caller, TFM_MEMORY_ACCESS_RW, privileged) != IPC_SUCCESS) {
tfm_panic();
}
}
@@ -363,6 +373,7 @@
struct tfm_spm_service_t *service = NULL;
struct tfm_msg_body_t *tmp_msg = NULL;
struct tfm_spm_ipc_partition_t *partition = NULL;
+ uint32_t privileged;
TFM_ASSERT(args != NULL);
signal = (psa_signal_t)args[0];
@@ -376,17 +387,18 @@
tfm_panic();
}
+ partition = tfm_spm_get_running_partition();
+ if (!partition) {
+ tfm_panic();
+ }
+ privileged = tfm_spm_partition_get_privileged_mode(partition->index);
+
/*
* Write the message to the service buffer. It is a fatal error if the
* input msg pointer is not a valid memory reference or not read-write.
*/
if (tfm_memory_check((void *)msg, sizeof(psa_msg_t),
- false, TFM_MEMORY_ACCESS_RW) != IPC_SUCCESS) {
- tfm_panic();
- }
-
- partition = tfm_spm_get_running_partition();
- if (!partition) {
+ false, TFM_MEMORY_ACCESS_RW, privileged) != IPC_SUCCESS) {
tfm_panic();
}
@@ -499,6 +511,8 @@
size_t num_bytes;
size_t bytes;
struct tfm_msg_body_t *msg = NULL;
+ uint32_t privileged;
+ struct tfm_spm_ipc_partition_t *partition = NULL;
TFM_ASSERT(args != NULL);
msg_handle = (psa_handle_t)args[0];
@@ -512,6 +526,9 @@
tfm_panic();
}
+ partition = msg->service->partition;
+ privileged = tfm_spm_partition_get_privileged_mode(partition->index);
+
/*
* It is a fatal error if message handle does not refer to a PSA_IPC_CALL
* message
@@ -538,7 +555,7 @@
* if the memory reference for buffer is invalid or not read-write.
*/
if (tfm_memory_check(buffer, num_bytes, false,
- TFM_MEMORY_ACCESS_RW) != IPC_SUCCESS) {
+ TFM_MEMORY_ACCESS_RW, privileged) != IPC_SUCCESS) {
tfm_panic();
}
@@ -650,6 +667,8 @@
void *buffer = NULL;
size_t num_bytes;
struct tfm_msg_body_t *msg = NULL;
+ uint32_t privileged;
+ struct tfm_spm_ipc_partition_t *partition = NULL;
TFM_ASSERT(args != NULL);
msg_handle = (psa_handle_t)args[0];
@@ -663,6 +682,9 @@
tfm_panic();
}
+ partition = msg->service->partition;
+ privileged = tfm_spm_partition_get_privileged_mode(partition->index);
+
/*
* It is a fatal error if message handle does not refer to a PSA_IPC_CALL
* message
@@ -693,7 +715,7 @@
* if the memory reference for buffer is invalid or not readable.
*/
if (tfm_memory_check(buffer, num_bytes, false,
- TFM_MEMORY_ACCESS_RO) != IPC_SUCCESS) {
+ TFM_MEMORY_ACCESS_RO, privileged) != IPC_SUCCESS) {
tfm_panic();
}
diff --git a/secure_fw/core/tfm_secure_api.c b/secure_fw/core/tfm_secure_api.c
index c2c89b2..4687342 100644
--- a/secure_fw/core/tfm_secure_api.c
+++ b/secure_fw/core/tfm_secure_api.c
@@ -204,9 +204,14 @@
}
int32_t tfm_core_has_read_access_to_region(const void *p, size_t s,
- uint32_t ns_caller)
+ uint32_t ns_caller,
+ uint32_t privileged)
{
- int flags = CMSE_MPU_UNPRIV|CMSE_MPU_READ;
+ int flags = CMSE_MPU_READ;
+
+ if (privileged == TFM_PARTITION_UNPRIVILEGED_MODE) {
+ flags |= CMSE_MPU_UNPRIV;
+ }
if (ns_caller) {
flags |= CMSE_NONSECURE;
@@ -216,9 +221,14 @@
}
int32_t tfm_core_has_write_access_to_region(void *p, size_t s,
- uint32_t ns_caller)
+ uint32_t ns_caller,
+ uint32_t privileged)
{
- int flags = CMSE_MPU_UNPRIV|CMSE_MPU_READWRITE;
+ int flags = CMSE_MPU_READWRITE;
+
+ if (privileged == TFM_PARTITION_UNPRIVILEGED_MODE) {
+ flags |= CMSE_MPU_UNPRIV;
+ }
if (ns_caller) {
flags |= CMSE_NONSECURE;
@@ -264,8 +274,8 @@
if (in_len > 0) {
if ((in_vec == NULL) ||
(tfm_core_has_write_access_to_region(in_vec,
- sizeof(psa_invec)*in_len,
- desc_ptr->ns_caller) != TFM_SUCCESS)) {
+ sizeof(psa_invec)*in_len, desc_ptr->ns_caller,
+ TFM_PARTITION_UNPRIVILEGED_MODE) != TFM_SUCCESS)) {
return TFM_ERROR_INVALID_PARAMETER;
}
} else {
@@ -276,8 +286,8 @@
if (out_len > 0) {
if ((out_vec == NULL) ||
(tfm_core_has_write_access_to_region(out_vec,
- sizeof(psa_outvec)*out_len,
- desc_ptr->ns_caller) != TFM_SUCCESS)) {
+ sizeof(psa_outvec)*out_len, desc_ptr->ns_caller,
+ TFM_PARTITION_UNPRIVILEGED_MODE) != TFM_SUCCESS)) {
return TFM_ERROR_INVALID_PARAMETER;
}
} else {
@@ -293,8 +303,8 @@
if (in_vec[i].len > 0) {
if ((in_vec[i].base == NULL) ||
(tfm_core_has_read_access_to_region(in_vec[i].base,
- in_vec[i].len,
- desc_ptr->ns_caller) != TFM_SUCCESS)) {
+ in_vec[i].len, desc_ptr->ns_caller,
+ TFM_PARTITION_UNPRIVILEGED_MODE) != TFM_SUCCESS)) {
return TFM_ERROR_INVALID_PARAMETER;
}
}
@@ -303,8 +313,8 @@
if (out_vec[i].len > 0) {
if ((out_vec[i].base == NULL) ||
(tfm_core_has_write_access_to_region(out_vec[i].base,
- out_vec[i].len,
- desc_ptr->ns_caller) != TFM_SUCCESS)) {
+ out_vec[i].len, desc_ptr->ns_caller,
+ TFM_PARTITION_UNPRIVILEGED_MODE) != TFM_SUCCESS)) {
return TFM_ERROR_INVALID_PARAMETER;
}
}
diff --git a/secure_fw/core/tfm_secure_api.h b/secure_fw/core/tfm_secure_api.h
index 88392a9..23bcd40 100644
--- a/secure_fw/core/tfm_secure_api.h
+++ b/secure_fw/core/tfm_secure_api.h
@@ -96,15 +96,19 @@
* This function assumes, that the current MPU configuration is set for the
* partition to be checked.
*
- * \param[in] p The start address of the range to check
- * \param[in] s The size of the range to check
- * \param[in] ns_caller Whether the current partition is a non-secure one
+ * \param[in] p The start address of the range to check
+ * \param[in] s The size of the range to check
+ * \param[in] ns_caller Whether the current partition is a non-secure one
+ * \param[in] privileged Privileged mode or unprivileged mode:
+ * \ref TFM_PARTITION_UNPRIVILEGED_MODE
+ * \ref TFM_PARTITION_PRIVILEGED_MODE
*
* \return TFM_SUCCESS if the partition has access to the memory range,
* TFM_ERROR_GENERIC otherwise.
*/
int32_t tfm_core_has_read_access_to_region(const void *p, size_t s,
- uint32_t ns_caller);
+ uint32_t ns_caller,
+ uint32_t privileged);
/**
* \brief Check whether the current partition has write access to a memory range
@@ -112,15 +116,19 @@
* This function assumes, that the current MPU configuration is set for the
* partition to be checked.
*
- * \param[in] p The start address of the range to check
- * \param[in] s The size of the range to check
- * \param[in] ns_caller Whether the current partition is a non-secure one
+ * \param[in] p The start address of the range to check
+ * \param[in] s The size of the range to check
+ * \param[in] ns_caller Whether the current partition is a non-secure one
+ * \param[in] privileged Privileged mode or unprivileged mode:
+ * \ref TFM_PARTITION_UNPRIVILEGED_MODE
+ * \ref TFM_PARTITION_PRIVILEGED_MODE
*
* \return TFM_SUCCESS if the partition has access to the memory range,
* TFM_ERROR_GENERIC otherwise.
*/
int32_t tfm_core_has_write_access_to_region(void *p, size_t s,
- uint32_t ns_caller);
+ uint32_t ns_caller,
+ uint32_t privileged);
#define TFM_CORE_IOVEC_SFN_REQUEST(id, fn, a, b, c, d) \
return tfm_core_partition_request(id, fn, TFM_SFN_API_IOVEC, \
diff --git a/secure_fw/spm/spm_api.h b/secure_fw/spm/spm_api.h
index 67accd5..87cc4e2 100644
--- a/secure_fw/spm/spm_api.h
+++ b/secure_fw/spm/spm_api.h
@@ -15,6 +15,10 @@
#define SPM_INVALID_PARTITION_IDX (~0U)
+/* Privileged definitions for partition thread mode */
+#define TFM_PARTITION_PRIVILEGED_MODE 1
+#define TFM_PARTITION_UNPRIVILEGED_MODE 0
+
enum spm_err_t {
SPM_ERR_OK = 0,
SPM_ERR_PARTITION_DB_NOT_INIT,