summaryrefslogtreecommitdiff
path: root/services/std_svc
diff options
context:
space:
mode:
authorManish Pandey <manish.pandey2@arm.com>2023-06-22 16:49:55 +0200
committerTrustedFirmware Code Review <review@review.trustedfirmware.org>2023-06-22 16:49:55 +0200
commit0ad935f72ae7daaf9cac6c65a207ce311bf98602 (patch)
treec01b55931f536c60b15450adfa24a24afe7ef2b3 /services/std_svc
parentf6b8e72506d5f93bb0362dcf58ee709df12f98a1 (diff)
parented23d274fae0b2787421a1b2558d7c1e9ebb07ab (diff)
Merge changes from topic "ffa_el3_spmc_fixes" into integration
* changes: fix(tsp): fix destination ID in direct request fix(el3-spm): fix LSP direct message response fix(el3-spm): improve direct messaging validation
Diffstat (limited to 'services/std_svc')
-rw-r--r--services/std_svc/spm/el3_spmc/spmc.h3
-rw-r--r--services/std_svc/spm/el3_spmc/spmc_main.c93
-rw-r--r--services/std_svc/spm/el3_spmc/spmc_pm.c2
3 files changed, 94 insertions, 4 deletions
diff --git a/services/std_svc/spm/el3_spmc/spmc.h b/services/std_svc/spm/el3_spmc/spmc.h
index 61afee30a..13875b913 100644
--- a/services/std_svc/spm/el3_spmc/spmc.h
+++ b/services/std_svc/spm/el3_spmc/spmc.h
@@ -131,6 +131,9 @@ struct sp_exec_ctx {
/* Track the current runtime model of the SP. */
enum sp_runtime_model rt_model;
+
+ /* Track the source partition ID to validate a direct response. */
+ uint16_t dir_req_origin_id;
};
/*
diff --git a/services/std_svc/spm/el3_spmc/spmc_main.c b/services/std_svc/spm/el3_spmc/spmc_main.c
index 08e7218d1..ada6f455d 100644
--- a/services/std_svc/spm/el3_spmc/spmc_main.c
+++ b/services/std_svc/spm/el3_spmc/spmc_main.c
@@ -260,6 +260,65 @@ static inline bool direct_msg_validate_arg2(uint64_t x2)
}
/*******************************************************************************
+ * Helper function to validate the destination ID of a direct response.
+ ******************************************************************************/
+static bool direct_msg_validate_dst_id(uint16_t dst_id)
+{
+ struct secure_partition_desc *sp;
+
+ /* Check if we're targeting a normal world partition. */
+ if (ffa_is_normal_world_id(dst_id)) {
+ return true;
+ }
+
+ /* Or directed to the SPMC itself.*/
+ if (dst_id == FFA_SPMC_ID) {
+ return true;
+ }
+
+ /* Otherwise ensure the SP exists. */
+ sp = spmc_get_sp_ctx(dst_id);
+ if (sp != NULL) {
+ return true;
+ }
+
+ return false;
+}
+
+/*******************************************************************************
+ * Helper function to validate the response from a Logical Partition.
+ ******************************************************************************/
+static bool direct_msg_validate_lp_resp(uint16_t origin_id, uint16_t lp_id,
+ void *handle)
+{
+ /* Retrieve populated Direct Response Arguments. */
+ uint64_t x1 = SMC_GET_GP(handle, CTX_GPREG_X1);
+ uint64_t x2 = SMC_GET_GP(handle, CTX_GPREG_X2);
+ uint16_t src_id = ffa_endpoint_source(x1);
+ uint16_t dst_id = ffa_endpoint_destination(x1);
+
+ if (src_id != lp_id) {
+ ERROR("Invalid EL3 LP source ID (0x%x).\n", src_id);
+ return false;
+ }
+
+ /*
+ * Check the destination ID is valid and ensure the LP is responding to
+ * the original request.
+ */
+ if ((!direct_msg_validate_dst_id(dst_id)) || (dst_id != origin_id)) {
+ ERROR("Invalid EL3 LP destination ID (0x%x).\n", dst_id);
+ return false;
+ }
+
+ if (!direct_msg_validate_arg2(x2)) {
+ ERROR("Invalid EL3 LP message encoding.\n");
+ return false;
+ }
+ return true;
+}
+
+/*******************************************************************************
* Handle direct request messages and route to the appropriate destination.
******************************************************************************/
static uint64_t direct_req_smc_handler(uint32_t smc_fid,
@@ -272,6 +331,7 @@ static uint64_t direct_req_smc_handler(uint32_t smc_fid,
void *handle,
uint64_t flags)
{
+ uint16_t src_id = ffa_endpoint_source(x1);
uint16_t dst_id = ffa_endpoint_destination(x1);
struct el3_lp_desc *el3_lp_descs;
struct secure_partition_desc *sp;
@@ -283,14 +343,29 @@ static uint64_t direct_req_smc_handler(uint32_t smc_fid,
FFA_ERROR_INVALID_PARAMETER);
}
+ /* Validate Sender is either the current SP or from the normal world. */
+ if ((secure_origin && src_id != spmc_get_current_sp_ctx()->sp_id) ||
+ (!secure_origin && !ffa_is_normal_world_id(src_id))) {
+ ERROR("Invalid direct request source ID (0x%x).\n", src_id);
+ return spmc_ffa_error_return(handle,
+ FFA_ERROR_INVALID_PARAMETER);
+ }
+
el3_lp_descs = get_el3_lp_array();
/* Check if the request is destined for a Logical Partition. */
for (unsigned int i = 0U; i < MAX_EL3_LP_DESCS_COUNT; i++) {
if (el3_lp_descs[i].sp_id == dst_id) {
- return el3_lp_descs[i].direct_req(
- smc_fid, secure_origin, x1, x2, x3, x4,
- cookie, handle, flags);
+ uint64_t ret = el3_lp_descs[i].direct_req(
+ smc_fid, secure_origin, x1, x2,
+ x3, x4, cookie, handle, flags);
+ if (!direct_msg_validate_lp_resp(src_id, dst_id,
+ handle)) {
+ panic();
+ }
+
+ /* Message checks out. */
+ return ret;
}
}
@@ -332,6 +407,7 @@ static uint64_t direct_req_smc_handler(uint32_t smc_fid,
*/
sp->ec[idx].rt_state = RT_STATE_RUNNING;
sp->ec[idx].rt_model = RT_MODEL_DIR_REQ;
+ sp->ec[idx].dir_req_origin_id = src_id;
return spmc_smc_return(smc_fid, secure_origin, x1, x2, x3, x4,
handle, cookie, flags, dst_id);
}
@@ -370,7 +446,7 @@ static uint64_t direct_resp_smc_handler(uint32_t smc_fid,
* Check that the response is either targeted to the Normal world or the
* SPMC e.g. a PM response.
*/
- if ((dst_id != FFA_SPMC_ID) && ffa_is_secure_world_id(dst_id)) {
+ if (!direct_msg_validate_dst_id(dst_id)) {
VERBOSE("Direct response to invalid partition ID (0x%x).\n",
dst_id);
return spmc_ffa_error_return(handle,
@@ -397,9 +473,18 @@ static uint64_t direct_resp_smc_handler(uint32_t smc_fid,
return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
}
+ if (sp->ec[idx].dir_req_origin_id != dst_id) {
+ WARN("Invalid direct resp partition ID 0x%x != 0x%x on core%u.\n",
+ dst_id, sp->ec[idx].dir_req_origin_id, idx);
+ return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
+ }
+
/* Update the state of the SP execution context. */
sp->ec[idx].rt_state = RT_STATE_WAITING;
+ /* Clear the ongoing direct request ID. */
+ sp->ec[idx].dir_req_origin_id = INV_SP_ID;
+
/*
* If the receiver is not the SPMC then forward the response to the
* Normal world.
diff --git a/services/std_svc/spm/el3_spmc/spmc_pm.c b/services/std_svc/spm/el3_spmc/spmc_pm.c
index d25344cb9..c7e864f37 100644
--- a/services/std_svc/spm/el3_spmc/spmc_pm.c
+++ b/services/std_svc/spm/el3_spmc/spmc_pm.c
@@ -83,6 +83,7 @@ static void spmc_cpu_on_finish_handler(u_register_t unused)
/* Update the runtime model and state of the partition. */
ec->rt_model = RT_MODEL_INIT;
ec->rt_state = RT_STATE_RUNNING;
+ ec->dir_req_origin_id = INV_SP_ID;
INFO("SP (0x%x) init start on core%u.\n", sp->sp_id, linear_id);
@@ -132,6 +133,7 @@ static int32_t spmc_send_pm_msg(uint8_t pm_msg_type,
/* Update the runtime model and state of the partition. */
ec->rt_model = RT_MODEL_DIR_REQ;
ec->rt_state = RT_STATE_RUNNING;
+ ec->dir_req_origin_id = FFA_SPMC_ID;
rc = spmc_sp_synchronous_entry(ec);
if (rc != 0ULL) {