fix(spmc): fix relinquish validation check

The current implementation expects that the endpoint IDs of all
participants of a memory transaction to be listed in the relinquish
descriptor. As per the FF-A spec, aside from the current partition
ID, only the IDs of stream endpoints whose behalf it is relinquishing
the memory region must be specified.

The current implementation does not currently support proxy endpoints
therefore ensure that the endpoint count is always equal to 1 and
no stream endpoint IDs are specified and instead just verify the
caller is a valid participant in the memory transaction.

Additionally reuse the updated check in the retrieve request flow
for additional verification.

Signed-off-by: Marc Bonnici <marc.bonnici@arm.com>
Change-Id: I3b970196af8a16b2531607775398cb8a2473793b
diff --git a/services/std_svc/spm/el3_spmc/spmc_shared_mem.c b/services/std_svc/spm/el3_spmc/spmc_shared_mem.c
index 4a24108..eab2096 100644
--- a/services/std_svc/spm/el3_spmc/spmc_shared_mem.c
+++ b/services/std_svc/spm/el3_spmc/spmc_shared_mem.c
@@ -260,6 +260,34 @@
 	return comp_mrd->address_range_count * sizeof(struct ffa_cons_mrd);
 }
 
+/**
+ * spmc_shmem_obj_validate_id - Validate a partition ID is participating in
+ *				a given memory transaction.
+ * @sp_id:      Partition ID to validate.
+ * @desc:       Descriptor of the memory transaction.
+ *
+ * Return: true if ID is valid, else false.
+ */
+bool spmc_shmem_obj_validate_id(const struct ffa_mtd *desc, uint16_t sp_id)
+{
+	bool found = false;
+
+	/* Validate the partition is a valid participant. */
+	for (unsigned int i = 0U; i < desc->emad_count; i++) {
+		size_t emad_size;
+		struct ffa_emad_v1_0 *emad;
+
+		emad = spmc_shmem_obj_get_emad(desc, i,
+					       MAKE_FFA_VERSION(1, 1),
+					       &emad_size);
+		if (sp_id == emad->mapd.endpoint_id) {
+			found = true;
+			break;
+		}
+	}
+	return found;
+}
+
 /*
  * Compare two memory regions to determine if any range overlaps with another
  * ongoing memory transaction.
@@ -1403,6 +1431,14 @@
 		}
 	}
 
+	/* Validate the caller is a valid participant. */
+	if (!spmc_shmem_obj_validate_id(&obj->desc, sp_ctx->sp_id)) {
+		WARN("%s: Invalid endpoint ID (0x%x).\n",
+			__func__, sp_ctx->sp_id);
+		ret = FFA_ERROR_INVALID_PARAMETER;
+		goto err_unlock_all;
+	}
+
 	/* Validate that the provided emad offset and structure is valid.*/
 	for (size_t i = 0; i < req->emad_count; i++) {
 		size_t emad_size;
@@ -1657,6 +1693,7 @@
 	struct mailbox *mbox = spmc_get_mbox_desc(secure_origin);
 	struct spmc_shmem_obj *obj;
 	const struct ffa_mem_relinquish_descriptor *req;
+	struct secure_partition_desc *sp_ctx = spmc_get_current_sp_ctx();
 
 	if (!secure_origin) {
 		WARN("%s: unsupported relinquish direction.\n", __func__);
@@ -1694,36 +1731,31 @@
 		goto err_unlock_all;
 	}
 
-	if (obj->desc.emad_count != req->endpoint_count) {
-		WARN("%s: mismatch of endpoint count %u != %u\n", __func__,
-		     obj->desc.emad_count, req->endpoint_count);
+	/*
+	 * Validate the endpoint ID was populated correctly. We don't currently
+	 * support proxy endpoints so the endpoint count should always be 1.
+	 */
+	if (req->endpoint_count != 1U) {
+		WARN("%s: unsupported endpoint count %u != 1\n", __func__,
+		     req->endpoint_count);
 		ret = FFA_ERROR_INVALID_PARAMETER;
 		goto err_unlock_all;
 	}
 
-	/* Validate requested endpoint IDs match descriptor. */
-	for (size_t i = 0; i < req->endpoint_count; i++) {
-		bool found = false;
-		size_t emad_size;
-		struct ffa_emad_v1_0 *emad;
+	/* Validate provided endpoint ID matches the partition ID. */
+	if (req->endpoint_array[0] != sp_ctx->sp_id) {
+		WARN("%s: invalid endpoint ID %u != %u\n", __func__,
+		     req->endpoint_array[0], sp_ctx->sp_id);
+		ret = FFA_ERROR_INVALID_PARAMETER;
+		goto err_unlock_all;
+	}
 
-		for (unsigned int j = 0; j < obj->desc.emad_count; j++) {
-			emad = spmc_shmem_obj_get_emad(&obj->desc, j,
-							MAKE_FFA_VERSION(1, 1),
-							&emad_size);
-			if (req->endpoint_array[i] ==
-			    emad->mapd.endpoint_id) {
-				found = true;
-				break;
-			}
-		}
-
-		if (!found) {
-			WARN("%s: Invalid endpoint ID (0x%x).\n",
-			     __func__, req->endpoint_array[i]);
-			ret = FFA_ERROR_INVALID_PARAMETER;
-			goto err_unlock_all;
-		}
+	/* Validate the caller is a valid participant. */
+	if (!spmc_shmem_obj_validate_id(&obj->desc, sp_ctx->sp_id)) {
+		WARN("%s: Invalid endpoint ID (0x%x).\n",
+			__func__, req->endpoint_array[0]);
+		ret = FFA_ERROR_INVALID_PARAMETER;
+		goto err_unlock_all;
 	}
 
 	if (obj->in_use == 0U) {