diff options
author | Summer Qin <summer.qin@arm.com> | 2019-10-14 18:04:05 +0800 |
---|---|---|
committer | Ken Liu <ken.liu@arm.com> | 2019-12-05 03:34:51 +0000 |
commit | 1ce712affb8be91ede0d1d9fd4f45d68201ac591 (patch) | |
tree | ff8ee2b5b4ff6820da928eb9e1cac440e205bc89 | |
parent | 8aae06ff913222e28055c792597ed43d00449d67 (diff) | |
download | trusted-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.c | 36 | ||||
-rw-r--r-- | secure_fw/spm/spm_api.h | 26 | ||||
-rw-r--r-- | secure_fw/spm/spm_api_ipc.c | 30 |
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; |