SPM: Improvements on connection handle creation and validation

This patch:

- Removes the duplicated 'client_id' in conn_handle_t as there
  is a 'cliend_id' in psa_msg_t struct already. 'client_id' will be
  populated by tfm_spm_fill_msg().

- Removes the 'magic' member in conn_handle_t as its validation
  can be covered by 'is_valid_chunk_data_in_pool()'.

- Simplifies the input args of handle creation and free API.

- Creates an API to get spm working handle from the client handle,
  it is an equivalent API of 'spm_get_handle_by_msg_handle()',
  which is used for partition APIs to get the spm working handle
  from message handle, and validates the partition id.

- Simplifies the check inside the handle validation API, moves the
  check of client id to the new API.

Change-Id: Ia81d868071f7ffe5a79fae97e12a67c56056e5bb
Signed-off-by: Kevin Peng <kevin.peng@arm.com>
Co-authored-by: Mingyang Sun <mingyang.sun@arm.com>
This commit is contained in:
Kevin Peng 2022-01-27 14:57:06 +08:00 committed by Ken Liu
parent 15a37f8c9e
commit e61e7050b6
4 changed files with 90 additions and 99 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2021, Arm Limited. All rights reserved.
* Copyright (c) 2018-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@ -73,7 +73,12 @@ typedef struct psa_msg_t {
psa_handle_t handle; /* A reference generated by the SPM to the
* message returned by psa_get().
*/
int32_t client_id; /* Partition ID of the sender of the message */
int32_t client_id; /*
* Partition ID of the sender of the
* message:
* - secure partition id;
* - non secure client endpoint id.
*/
void *rhandle; /* Be useful for binding a connection to some
* application-specific data or function
* pointer within the RoT Service

View File

@ -147,13 +147,10 @@ struct conn_handle_t *tfm_spm_to_handle_instance(psa_handle_t user_handle)
}
/* Service handle management functions */
struct conn_handle_t *tfm_spm_create_conn_handle(struct service_t *service,
int32_t client_id)
struct conn_handle_t *tfm_spm_create_conn_handle(void)
{
struct conn_handle_t *p_handle;
TFM_CORE_ASSERT(service);
/* Get buffer for handle list structure from handle pool */
p_handle = (struct conn_handle_t *)tfm_pool_alloc(conn_handle_pool);
if (!p_handle) {
@ -162,45 +159,31 @@ struct conn_handle_t *tfm_spm_create_conn_handle(struct service_t *service,
spm_memset(p_handle, 0, sizeof(*p_handle));
p_handle->service = service;
p_handle->status = TFM_HANDLE_STATUS_IDLE;
p_handle->client_id = client_id;
return p_handle;
}
#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
int32_t tfm_spm_validate_conn_handle(const struct conn_handle_t *conn_handle,
int32_t client_id)
int32_t tfm_spm_validate_conn_handle(const struct conn_handle_t *conn_handle)
{
/* Check the handle address is validated */
/* Check the handle address is valid */
if (is_valid_chunk_data_in_pool(conn_handle_pool,
(uint8_t *)conn_handle) != true) {
return SPM_ERROR_GENERIC;
}
/* Check the handle caller is correct */
if (conn_handle->client_id != client_id) {
return SPM_ERROR_GENERIC;
}
return SPM_SUCCESS;
}
#endif
int32_t tfm_spm_free_conn_handle(struct service_t *service,
struct conn_handle_t *conn_handle)
int32_t tfm_spm_free_conn_handle(struct conn_handle_t *conn_handle)
{
struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
TFM_CORE_ASSERT(service);
TFM_CORE_ASSERT(conn_handle != NULL);
/* Clear magic as the handler is not used anymore */
conn_handle->magic = 0;
CRITICAL_SECTION_ENTER(cs_assert);
/* Back handle buffer to pool */
tfm_pool_free(conn_handle_pool, conn_handle);
CRITICAL_SECTION_LEAVE(cs_assert);
@ -342,7 +325,24 @@ int32_t tfm_spm_check_authorization(uint32_t sid,
/* Message functions */
struct conn_handle_t *spm_get_handle_by_user_handle(psa_handle_t msg_handle)
struct conn_handle_t *spm_get_handle_by_client_handle(psa_handle_t handle,
int32_t client_id)
{
struct conn_handle_t *p_conn_handle = tfm_spm_to_handle_instance(handle);
if (tfm_spm_validate_conn_handle(p_conn_handle) != SPM_SUCCESS) {
return NULL;
}
/* Validate the caller id in the connection handle equals client_id. */
if (p_conn_handle->msg.client_id != client_id) {
return NULL;
}
return p_conn_handle;
}
struct conn_handle_t *spm_get_handle_by_msg_handle(psa_handle_t msg_handle)
{
/*
* The message handler passed by the caller is considered invalid in the
@ -357,16 +357,7 @@ struct conn_handle_t *spm_get_handle_by_user_handle(psa_handle_t msg_handle)
struct conn_handle_t *p_conn_handle =
tfm_spm_to_handle_instance(msg_handle);
if (is_valid_chunk_data_in_pool(
conn_handle_pool, (uint8_t *)p_conn_handle) != true) {
return NULL;
}
/*
* Check that the magic number is correct. This proves that the message
* structure contains an active message.
*/
if (p_conn_handle->magic != TFM_MSG_MAGIC) {
if (tfm_spm_validate_conn_handle(p_conn_handle) != SPM_SUCCESS) {
return NULL;
}
@ -401,7 +392,6 @@ void spm_fill_message(struct conn_handle_t *conn_handle,
spm_memset(&conn_handle->msg, 0, sizeof(psa_msg_t));
THRD_SYNC_INIT(&conn_handle->ack_evnt);
conn_handle->magic = TFM_MSG_MAGIC;
conn_handle->service = service;
conn_handle->p_client = GET_CURRENT_COMPONENT();
conn_handle->caller_outvec = caller_outvec;

View File

@ -70,7 +70,6 @@
#define SPM_INVALID_PARTITION_IDX (~0U)
#define TFM_MSG_MAGIC 0x15154343
#define TFM_MSG_MAGIC_SFN 0x21216565
/* Get partition by thread or context data */
@ -79,7 +78,7 @@
/* RoT connection handle list */
struct conn_handle_t {
void *rhandle; /* Reverse handle value */
void *rhandle; /* Reverse handle value */
uint32_t status; /*
* Status of handle, three valid
* options:
@ -87,37 +86,30 @@ struct conn_handle_t {
* TFM_HANDLE_STATUS_IDLE and
* TFM_HANDLE_STATUS_CONNECT_ERROR
*/
int32_t client_id; /*
* Partition ID of the sender of the
* message:
* - secure partition id;
* - non secure client endpoint id.
*/
int32_t magic;
struct partition_t *p_client; /* Caller partition */
struct service_t *service; /* RoT service pointer */
struct partition_t *p_client; /* Caller partition */
struct service_t *service; /* RoT service pointer */
union {
struct sync_obj_t ack_evnt; /* IPC - Ack response event */
uint32_t sfn_magic; /* SFN - Indicate a SFN message */
struct sync_obj_t ack_evnt; /* IPC - Ack response event */
uint32_t sfn_magic; /* SFN - Indicate a SFN message */
};
psa_msg_t msg; /* PSA message body */
psa_invec invec[PSA_MAX_IOVEC]; /* Put in/out vectors in msg body */
psa_msg_t msg; /* PSA message body */
psa_invec invec[PSA_MAX_IOVEC]; /* Put in/out vectors in msg body */
psa_outvec outvec[PSA_MAX_IOVEC];
psa_outvec *caller_outvec; /*
* Save caller outvec pointer for
* write length update
*/
psa_outvec *caller_outvec; /*
* Save caller outvec pointer for
* write length update
*/
#ifdef TFM_MULTI_CORE_TOPOLOGY
const void *caller_data; /*
* Pointer to the private data of the
* caller. It identifies the NSPE PSA
* client calls in multi-core topology
*/
const void *caller_data; /*
* Pointer to the private data of the
* caller. It identifies the NSPE PSA
* client calls in multi-core topology
*/
#endif
#if PSA_FRAMEWORK_HAS_MM_IOVEC
uint32_t iovec_status; /* MM-IOVEC status */
uint32_t iovec_status; /* MM-IOVEC status */
#endif
struct conn_handle_t *p_handles; /* Handle(s) link */
struct conn_handle_t *p_handles; /* Handle(s) link */
};
/* Partition runtime type */
@ -163,31 +155,24 @@ int32_t tfm_spm_partition_get_running_partition_id(void);
/**
* \brief Create connection handle for client connect
*
* \param[in] service Target service context pointer
* \param[in] client_id Partition ID of the sender
*
* \retval NULL Create failed
* \retval "Not NULL" Service handle created
*/
struct conn_handle_t *tfm_spm_create_conn_handle(struct service_t *service,
int32_t client_id);
struct conn_handle_t *tfm_spm_create_conn_handle(void);
/**
* \brief Validate connection handle for client connect
*
* \param[in] conn_handle Handle to be validated
* \param[in] client_id Partition ID of the sender
*
* \retval SPM_SUCCESS Success
* \retval SPM_ERROR_GENERIC Invalid handle
*/
int32_t tfm_spm_validate_conn_handle(const struct conn_handle_t *conn_handle,
int32_t client_id);
int32_t tfm_spm_validate_conn_handle(const struct conn_handle_t *conn_handle);
/**
* \brief Free connection handle which not used anymore.
*
* \param[in] service Target service context pointer
* \param[in] conn_handle Connection handle created by
* tfm_spm_create_conn_handle()
*
@ -195,8 +180,7 @@ int32_t tfm_spm_validate_conn_handle(const struct conn_handle_t *conn_handle,
* \retval SPM_ERROR_BAD_PARAMETERS Bad parameters input
* \retval "Does not return" Panic for not find service by handle
*/
int32_t tfm_spm_free_conn_handle(struct service_t *service,
struct conn_handle_t *conn_handle);
int32_t tfm_spm_free_conn_handle(struct conn_handle_t *conn_handle);
/******************** Partition management functions *************************/
@ -243,17 +227,31 @@ struct service_t *tfm_spm_get_service_by_sid(uint32_t sid);
/************************ Message functions **********************************/
/**
* \brief Get spm work handle by given user handle.
* \brief Convert the given client handle to SPM recognised
* handle and verify it.
*
* \param[in] msg_handle Message handle which is a reference generated
* by the SPM to a specific message. A few
* validations happen in this function before
* the final result returns.
* \param[in] handle A handle to an established connection that is
* returned by a prior psa_connect call.
*
* \return The spm work handle.
* \return A SPM recognised handle or NULL. It is NULL when
* verification of the converted SPM handle fails.
* \ref conn_handle_t structures
*/
struct conn_handle_t *spm_get_handle_by_user_handle(psa_handle_t msg_handle);
struct conn_handle_t *spm_get_handle_by_client_handle(psa_handle_t handle,
int32_t client_id);
/**
* \brief Convert the given message handle to SPM recognised
* handle and verify it.
*
* \param[in] msg_handle Message handle which is a reference generated
* by the SPM to a specific message.
*
* \return A SPM recognised handle or NULL. It is NULL when
* verification of the converted SPM handle fails.
* \ref conn_handle_t structures
*/
struct conn_handle_t *spm_get_handle_by_msg_handle(psa_handle_t msg_handle);
/**
* \brief Fill the user message in handle.

View File

@ -204,7 +204,7 @@ psa_status_t tfm_spm_client_psa_call(psa_handle_t handle,
}
CRITICAL_SECTION_ENTER(cs_assert);
conn_handle = tfm_spm_create_conn_handle(service, client_id);
conn_handle = tfm_spm_create_conn_handle();
CRITICAL_SECTION_LEAVE(cs_assert);
if (!conn_handle) {
@ -215,11 +215,9 @@ psa_status_t tfm_spm_client_psa_call(psa_handle_t handle,
handle = tfm_spm_to_user_handle(conn_handle);
} else {
#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
conn_handle = tfm_spm_to_handle_instance(handle);
/* It is a PROGRAMMER ERROR if an invalid handle was passed. */
if (tfm_spm_validate_conn_handle(conn_handle, client_id)
!= SPM_SUCCESS) {
conn_handle = spm_get_handle_by_client_handle(handle, client_id);
if (!conn_handle) {
return PSA_ERROR_PROGRAMMER_ERROR;
}
@ -372,7 +370,7 @@ psa_status_t tfm_spm_client_psa_connect(uint32_t sid, uint32_t version)
* code to client when creation fails.
*/
CRITICAL_SECTION_ENTER(cs_assert);
conn_handle = tfm_spm_create_conn_handle(service, client_id);
conn_handle = tfm_spm_create_conn_handle();
CRITICAL_SECTION_LEAVE(cs_assert);
if (!conn_handle) {
return PSA_ERROR_CONNECTION_BUSY;
@ -405,12 +403,12 @@ psa_status_t tfm_spm_client_psa_close(psa_handle_t handle)
client_id = tfm_spm_get_client_id(ns_caller);
conn_handle = tfm_spm_to_handle_instance(handle);
/*
* It is a PROGRAMMER ERROR if an invalid handle was provided that is not
* the null handle.
*/
if (tfm_spm_validate_conn_handle(conn_handle, client_id) != SPM_SUCCESS) {
conn_handle = spm_get_handle_by_client_handle(handle, client_id);
if (!conn_handle) {
return PSA_ERROR_PROGRAMMER_ERROR;
}
@ -546,7 +544,7 @@ size_t tfm_spm_partition_psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
uint32_t priv_mode;
/* It is a fatal error if message handle is invalid */
handle = spm_get_handle_by_user_handle(msg_handle);
handle = spm_get_handle_by_msg_handle(msg_handle);
if (!handle) {
tfm_core_panic();
}
@ -615,7 +613,7 @@ size_t tfm_spm_partition_psa_skip(psa_handle_t msg_handle, uint32_t invec_idx,
struct conn_handle_t *handle = NULL;
/* It is a fatal error if message handle is invalid */
handle = spm_get_handle_by_user_handle(msg_handle);
handle = spm_get_handle_by_msg_handle(msg_handle);
if (!handle) {
tfm_core_panic();
}
@ -676,7 +674,7 @@ void tfm_spm_partition_psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
uint32_t priv_mode;
/* It is a fatal error if message handle is invalid */
handle = spm_get_handle_by_user_handle(msg_handle);
handle = spm_get_handle_by_msg_handle(msg_handle);
if (!handle) {
tfm_core_panic();
}
@ -746,7 +744,7 @@ psa_status_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
/* It is a fatal error if message handle is invalid */
handle = spm_get_handle_by_user_handle(msg_handle);
handle = spm_get_handle_by_msg_handle(msg_handle);
if (!handle) {
tfm_core_panic();
}
@ -772,7 +770,7 @@ psa_status_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
ret = msg_handle;
} else if (status == PSA_ERROR_CONNECTION_REFUSED) {
/* Refuse the client connection, indicating a permanent error. */
tfm_spm_free_conn_handle(service, handle);
tfm_spm_free_conn_handle(handle);
ret = PSA_ERROR_CONNECTION_REFUSED;
} else if (status == PSA_ERROR_CONNECTION_BUSY) {
/* Fail the client connection, indicating a transient error. */
@ -783,7 +781,7 @@ psa_status_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
break;
case PSA_IPC_DISCONNECT:
/* Service handle is not used anymore */
tfm_spm_free_conn_handle(service, handle);
tfm_spm_free_conn_handle(handle);
/*
* If the message type is PSA_IPC_DISCONNECT, then the status code is
@ -826,7 +824,7 @@ psa_status_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
*/
update_caller_outvec_len(handle);
if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
tfm_spm_free_conn_handle(service, handle);
tfm_spm_free_conn_handle(handle);
}
} else {
tfm_core_panic();
@ -909,7 +907,7 @@ void tfm_spm_partition_psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
struct conn_handle_t *handle;
/* It is a fatal error if message handle is invalid */
handle = spm_get_handle_by_user_handle(msg_handle);
handle = spm_get_handle_by_msg_handle(msg_handle);
if (!handle) {
tfm_core_panic();
}
@ -1035,7 +1033,7 @@ const void *tfm_spm_partition_psa_map_invec(psa_handle_t msg_handle,
struct partition_t *partition = NULL;
/* It is a fatal error if message handle is invalid */
handle = spm_get_handle_by_user_handle(msg_handle);
handle = spm_get_handle_by_msg_handle(msg_handle);
if (!handle) {
tfm_core_panic();
}
@ -1110,7 +1108,7 @@ void tfm_spm_partition_psa_unmap_invec(psa_handle_t msg_handle,
struct conn_handle_t *handle;
/* It is a fatal error if message handle is invalid */
handle = spm_get_handle_by_user_handle(msg_handle);
handle = spm_get_handle_by_msg_handle(msg_handle);
if (!handle) {
tfm_core_panic();
}
@ -1166,7 +1164,7 @@ void *tfm_spm_partition_psa_map_outvec(psa_handle_t msg_handle,
struct partition_t *partition = NULL;
/* It is a fatal error if message handle is invalid */
handle = spm_get_handle_by_user_handle(msg_handle);
handle = spm_get_handle_by_msg_handle(msg_handle);
if (!handle) {
tfm_core_panic();
}
@ -1238,7 +1236,7 @@ void tfm_spm_partition_psa_unmap_outvec(psa_handle_t msg_handle,
struct conn_handle_t *handle;
/* It is a fatal error if message handle is invalid */
handle = spm_get_handle_by_user_handle(msg_handle);
handle = spm_get_handle_by_msg_handle(msg_handle);
if (!handle) {
tfm_core_panic();
}