aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSummer Qin <summer.qin@arm.com>2019-10-14 18:04:05 +0800
committerKen Liu <ken.liu@arm.com>2019-12-05 03:34:51 +0000
commit1ce712affb8be91ede0d1d9fd4f45d68201ac591 (patch)
treeff8ee2b5b4ff6820da928eb9e1cac440e205bc89
parent8aae06ff913222e28055c792597ed43d00449d67 (diff)
downloadtrusted-firmware-m-1ce712affb8be91ede0d1d9fd4f45d68201ac591.tar.gz
Core: Add connect handle check
Check from the two aspects: - Check the validation of the connection handle by checking if it is allocated from conn_handle_pool. - Check the ownership of the connection handle by checking if the client_id stored in handle is the same as the current caller. Change-Id: I4a6031f34d022760800acf1c3a41c4f7dc7747cc Signed-off-by: Summer Qin <summer.qin@arm.com>
-rw-r--r--secure_fw/core/ipc/tfm_psa_client_call.c36
-rw-r--r--secure_fw/spm/spm_api.h26
-rw-r--r--secure_fw/spm/spm_api_ipc.c30
3 files changed, 77 insertions, 15 deletions
diff --git a/secure_fw/core/ipc/tfm_psa_client_call.c b/secure_fw/core/ipc/tfm_psa_client_call.c
index 668a262e97..40ba17e572 100644
--- a/secure_fw/core/ipc/tfm_psa_client_call.c
+++ b/secure_fw/core/ipc/tfm_psa_client_call.c
@@ -15,6 +15,7 @@
#include "tfm_psa_client_call.h"
#include "tfm_utils.h"
#include "tfm_wait.h"
+#include "tfm_nspm.h"
uint32_t tfm_psa_framework_version(void)
{
@@ -51,6 +52,7 @@ psa_status_t tfm_psa_connect(uint32_t sid, uint32_t version,
struct tfm_spm_service_t *service;
struct tfm_msg_body_t *msg;
psa_handle_t connect_handle;
+ int32_t client_id;
/* It is a fatal error if the RoT Service does not exist on the platform */
service = tfm_spm_get_service_by_sid(sid);
@@ -58,11 +60,17 @@ psa_status_t tfm_psa_connect(uint32_t sid, uint32_t version,
tfm_panic();
}
+ if (ns_caller) {
+ client_id = tfm_nspm_get_current_client_id();
+ } else {
+ client_id = tfm_spm_partition_get_running_partition_id();
+ }
+
/*
* Create connection handle here since it is possible to return the error
* code to client when creation fails.
*/
- connect_handle = tfm_spm_create_conn_handle(service);
+ connect_handle = tfm_spm_create_conn_handle(service, client_id);
if (connect_handle == PSA_NULL_HANDLE) {
return PSA_ERROR_CONNECTION_BUSY;
}
@@ -91,7 +99,7 @@ psa_status_t tfm_psa_connect(uint32_t sid, uint32_t version,
/* No input or output needed for connect message */
tfm_spm_fill_msg(msg, service, connect_handle, PSA_IPC_CONNECT,
- ns_caller, NULL, 0, NULL, 0, NULL);
+ client_id, NULL, 0, NULL, 0, NULL);
/*
* Send message and wake up the SP who is waiting on message queue,
@@ -112,6 +120,7 @@ psa_status_t tfm_psa_call(psa_handle_t handle, int32_t type,
struct tfm_spm_service_t *service;
struct tfm_msg_body_t *msg;
int i;
+ int32_t client_id;
/* It is a fatal error if in_len + out_len > PSA_MAX_IOVEC. */
if ((in_num > PSA_MAX_IOVEC) ||
@@ -120,7 +129,16 @@ psa_status_t tfm_psa_call(psa_handle_t handle, int32_t type,
tfm_panic();
}
+ if (ns_caller) {
+ client_id = tfm_nspm_get_current_client_id();
+ } else {
+ client_id = tfm_spm_partition_get_running_partition_id();
+ }
+
/* It is a fatal error if an invalid handle was passed. */
+ if (tfm_spm_validate_conn_handle(handle, client_id) != IPC_SUCCESS) {
+ tfm_panic();
+ }
service = tfm_spm_get_service_by_handle(handle);
if (!service) {
/* FixMe: Need to implement one mechanism to resolve this failure. */
@@ -184,7 +202,7 @@ psa_status_t tfm_psa_call(psa_handle_t handle, int32_t type,
tfm_panic();
}
- tfm_spm_fill_msg(msg, service, handle, type, ns_caller, invecs,
+ tfm_spm_fill_msg(msg, service, handle, type, client_id, invecs,
in_num, outvecs, out_num, outptr);
/*
@@ -202,16 +220,26 @@ void tfm_psa_close(psa_handle_t handle, int32_t ns_caller)
{
struct tfm_spm_service_t *service;
struct tfm_msg_body_t *msg;
+ int32_t client_id;
/* It will have no effect if called with the NULL handle */
if (handle == PSA_NULL_HANDLE) {
return;
}
+ if (ns_caller) {
+ client_id = tfm_nspm_get_current_client_id();
+ } else {
+ client_id = tfm_spm_partition_get_running_partition_id();
+ }
+
/*
* It is a fatal error if an invalid handle was provided that is not the
* null handle.
*/
+ if (tfm_spm_validate_conn_handle(handle, client_id) != IPC_SUCCESS) {
+ tfm_panic();
+ }
service = tfm_spm_get_service_by_handle(handle);
if (!service) {
/* FixMe: Need to implement one mechanism to resolve this failure. */
@@ -231,7 +259,7 @@ void tfm_psa_close(psa_handle_t handle, int32_t ns_caller)
}
/* No input or output needed for close message */
- tfm_spm_fill_msg(msg, service, handle, PSA_IPC_DISCONNECT, ns_caller,
+ tfm_spm_fill_msg(msg, service, handle, PSA_IPC_DISCONNECT, client_id,
NULL, 0, NULL, 0, NULL);
/*
diff --git a/secure_fw/spm/spm_api.h b/secure_fw/spm/spm_api.h
index 9929b3c336..35be8c2ce8 100644
--- a/secure_fw/spm/spm_api.h
+++ b/secure_fw/spm/spm_api.h
@@ -123,6 +123,12 @@ struct tfm_conn_handle_t {
* TFM_HANDLE_STATUS_ACTIVE and
* TFM_HANDLE_STATUS_IDLE
*/
+ int32_t client_id; /*
+ * Partition ID of the sender of the
+ * message:
+ * - secure partition id;
+ * - non secure client endpoint id.
+ */
struct tfm_msg_body_t internal_msg; /* Internal message for message queue */
struct tfm_spm_service_t *service; /* RoT service pointer */
struct tfm_list_node_t list; /* list node */
@@ -412,11 +418,25 @@ uint32_t tfm_spm_partition_get_privileged_mode(uint32_t partition_flags);
* \brief Create connection handle for client connect
*
* \param[in] service Target service context pointer
+ * \param[in] client_id Partition ID of the sender of the message
*
* \retval PSA_NULL_HANDLE Create failed \ref PSA_NULL_HANDLE
* \retval >0 Service handle created, \ref psa_handle_t
*/
-psa_handle_t tfm_spm_create_conn_handle(struct tfm_spm_service_t *service);
+psa_handle_t tfm_spm_create_conn_handle(struct tfm_spm_service_t *service,
+ int32_t client_id);
+
+/**
+ * \brief Validate connection handle for client connect
+ *
+ * \param[in] conn_handle Handle to be validated
+ * \param[in] client_id Partition ID of the sender of the message
+ *
+ * \retval IPC_SUCCESS Success
+ * \retval IPC_ERROR_GENERIC Invalid handle
+ */
+int32_t tfm_spm_validate_conn_handle(psa_handle_t conn_handle,
+ int32_t client_id);
/**
* \brief Free connection handle which not used anymore.
@@ -560,7 +580,7 @@ struct tfm_msg_body_t *
* \prarm[in] handle Connect handle return by psa_connect().
* \param[in] type Message type, PSA_IPC_CONNECT, PSA_IPC_CALL or
* PSA_IPC_DISCONNECT
- * \param[in] ns_caller Whether from NS caller
+ * \param[in] client_id Partition ID of the sender of the message
* \param[in] invec Array of input \ref psa_invec structures
* \param[in] in_len Number of input \ref psa_invec structures
* \param[in] outvec Array of output \ref psa_outvec structures
@@ -570,7 +590,7 @@ struct tfm_msg_body_t *
void tfm_spm_fill_msg(struct tfm_msg_body_t *msg,
struct tfm_spm_service_t *service,
psa_handle_t handle,
- int32_t type, int32_t ns_caller,
+ int32_t type, int32_t client_id,
psa_invec *invec, size_t in_len,
psa_outvec *outvec, size_t out_len,
psa_outvec *caller_outvec);
diff --git a/secure_fw/spm/spm_api_ipc.c b/secure_fw/spm/spm_api_ipc.c
index 58a0fd37c8..4933e97f65 100644
--- a/secure_fw/spm/spm_api_ipc.c
+++ b/secure_fw/spm/spm_api_ipc.c
@@ -50,7 +50,8 @@ TFM_POOL_DECLARE(conn_handle_pool, sizeof(struct tfm_conn_handle_t),
/********************** SPM functions for handler mode ***********************/
/* Service handle management functions */
-psa_handle_t tfm_spm_create_conn_handle(struct tfm_spm_service_t *service)
+psa_handle_t tfm_spm_create_conn_handle(struct tfm_spm_service_t *service,
+ int32_t client_id)
{
struct tfm_conn_handle_t *p_handle;
@@ -64,6 +65,7 @@ psa_handle_t tfm_spm_create_conn_handle(struct tfm_spm_service_t *service)
p_handle->service = service;
p_handle->status = TFM_HANDLE_STATUS_IDLE;
+ p_handle->client_id = client_id;
/* Add handle node to list for next psa functions */
tfm_list_add_tail(&service->handle_list, &p_handle->list);
@@ -71,6 +73,23 @@ psa_handle_t tfm_spm_create_conn_handle(struct tfm_spm_service_t *service)
return (psa_handle_t)p_handle;
}
+int32_t tfm_spm_validate_conn_handle(psa_handle_t conn_handle,
+ int32_t client_id)
+{
+ /* Check the handle address is validated */
+ if (is_valid_chunk_data_in_pool(conn_handle_pool,
+ (uint8_t *)conn_handle) != true) {
+ return IPC_ERROR_GENERIC;
+ }
+
+ /* Check the handle caller is correct */
+ if (((struct tfm_conn_handle_t *)conn_handle)->client_id != client_id) {
+ return IPC_ERROR_GENERIC;
+ }
+
+ return IPC_SUCCESS;
+}
+
static struct tfm_conn_handle_t *
tfm_spm_find_conn_handle_node(struct tfm_spm_service_t *service,
psa_handle_t conn_handle)
@@ -304,7 +323,7 @@ struct tfm_msg_body_t *
void tfm_spm_fill_msg(struct tfm_msg_body_t *msg,
struct tfm_spm_service_t *service,
psa_handle_t handle,
- int32_t type, int32_t ns_caller,
+ int32_t type, int32_t client_id,
psa_invec *invec, size_t in_len,
psa_outvec *outvec, size_t out_len,
psa_outvec *caller_outvec)
@@ -327,12 +346,7 @@ void tfm_spm_fill_msg(struct tfm_msg_body_t *msg,
msg->service = service;
msg->handle = handle;
msg->caller_outvec = caller_outvec;
- /* Get current partition id */
- if (ns_caller) {
- msg->msg.client_id = tfm_nspm_get_current_client_id();
- } else {
- msg->msg.client_id = tfm_spm_partition_get_running_partition_id();
- }
+ msg->msg.client_id = client_id;
/* Copy contents */
msg->msg.type = type;