refactor(memory share): use receiver_offsets to find receiver array

The receiver_offsets field was introduced to the ffa_memory_region
struct to help with forwards compatability in future FF-A versions
as the size of the `ffa_memory_region` struct varies. This patch moves
away from using `sizeof(ffa_memory_region)` to find the receiver array
and instead to using the `receivers_offset` field.

This is safe to do due to the introdution to the use of the
`ffa_memory_region_check_values` function in the previous patch.

Signed-off-by: Daniel Boulby <daniel.boulby@arm.com>
Change-Id: I6aac59df0ad19ef500550d1bd60d1519a125598a
diff --git a/inc/vmapi/hf/ffa.h b/inc/vmapi/hf/ffa.h
index 23f0677..b600957 100644
--- a/inc/vmapi/hf/ffa.h
+++ b/inc/vmapi/hf/ffa.h
@@ -1155,13 +1155,6 @@
 	uint32_t receivers_offset;
 	/** Reserved field (12 bytes) must be 0. */
 	uint32_t reserved[3];
-	/**
-	 * An array of `receiver_count` endpoint memory access descriptors.
-	 * Each one specifies a memory region offset, an endpoint and the
-	 * attributes with which this memory region should be mapped in that
-	 * endpoint's page table.
-	 */
-	struct ffa_memory_access receivers[];
 };
 
 /**
@@ -1215,8 +1208,14 @@
 		return NULL;
 	}
 
-	return (struct ffa_memory_access *)((uint8_t *)
-						    memory_region->receivers +
+	/* Check we cannot use receivers offset to cause overflow. */
+	if (memory_region->receivers_offset !=
+	    sizeof(struct ffa_memory_region)) {
+		return NULL;
+	}
+
+	return (struct ffa_memory_access *)((uint8_t *)memory_region +
+					    memory_region->receivers_offset +
 					    (receiver_index *
 					     memory_access_desc_size));
 }
diff --git a/src/api.c b/src/api.c
index a124abd..9d08db9 100644
--- a/src/api.c
+++ b/src/api.c
@@ -3026,8 +3026,7 @@
 	memory_region_v1_1->memory_access_desc_size =
 		sizeof(struct ffa_memory_access_v1_0);
 	memory_region_v1_1->receiver_count = memory_region_v1_0->receiver_count;
-	memory_region_v1_1->receivers_offset =
-		offsetof(struct ffa_memory_region, receivers);
+	memory_region_v1_1->receivers_offset = sizeof(struct ffa_memory_region);
 
 	/* Zero reserved fields. */
 	for (uint32_t i = 0; i < 3U; i++) {
@@ -3147,8 +3146,9 @@
 	space_left -= sizeof(struct ffa_memory_region);
 
 	/* Copy memory access information. */
-	memcpy_s(memory_region_v1_1->receivers, space_left,
-		 memory_region_v1_0->receivers, receivers_length);
+	memcpy_s((uint8_t *)memory_region_v1_1 +
+			 memory_region_v1_1->receivers_offset,
+		 space_left, memory_region_v1_0->receivers, receivers_length);
 
 	/* Initialize the memory access descriptors with composite offset. */
 	for (uint32_t i = 0; i < memory_region_v1_1->receiver_count; i++) {
diff --git a/src/ffa_memory.c b/src/ffa_memory.c
index 820d010..e146121 100644
--- a/src/ffa_memory.c
+++ b/src/ffa_memory.c
@@ -1467,6 +1467,7 @@
 {
 	struct ffa_memory_region *memory_region = share_state->memory_region;
 	struct ffa_composite_memory_region *composite;
+	struct ffa_memory_access *receiver;
 	struct ffa_value ret;
 
 	/* Lock must be held. */
@@ -1474,13 +1475,15 @@
 	assert(memory_region != NULL);
 	composite = ffa_memory_region_get_composite(memory_region, 0);
 	assert(composite != NULL);
+	receiver = ffa_memory_region_get_receiver(memory_region, 0);
+	assert(receiver != NULL);
 
 	/* Check that state is valid in sender page table and update. */
 	ret = ffa_send_check_update(
 		from_locked, share_state->fragments,
 		share_state->fragment_constituent_counts,
 		share_state->fragment_count, composite->page_count,
-		share_state->share_func, memory_region->receivers,
+		share_state->share_func, receiver,
 		memory_region->receiver_count, page_pool,
 		memory_region->flags & FFA_MEMORY_REGION_FLAG_CLEAR,
 		orig_from_mode_ret);
@@ -1563,9 +1566,9 @@
 	enum ffa_memory_security security_state;
 	struct ffa_value ret;
 	const size_t minimum_first_fragment_length =
-		(sizeof(struct ffa_memory_region) +
-		 memory_region->memory_access_desc_size +
-		 sizeof(struct ffa_composite_memory_region));
+		memory_region->receivers_offset +
+		memory_region->memory_access_desc_size +
+		sizeof(struct ffa_composite_memory_region);
 
 	if (fragment_length < minimum_first_fragment_length) {
 		dlog_verbose("Fragment length %u too short (min %u).\n",
@@ -1594,9 +1597,6 @@
 		return ffa_error(FFA_INVALID_PARAMETERS);
 	}
 
-	assert(memory_region->receivers_offset ==
-	       offsetof(struct ffa_memory_region, receivers));
-
 	/* The sender must match the caller. */
 	if ((!vm_id_is_current_world(from_locked.vm->id) &&
 	     vm_id_is_current_world(memory_region->sender)) ||
@@ -1618,7 +1618,7 @@
 	 */
 	receivers_end = ((uint64_t)memory_region->memory_access_desc_size *
 			 (uint64_t)memory_region->receiver_count) +
-			sizeof(struct ffa_memory_region);
+			memory_region->receivers_offset;
 	min_length = receivers_end +
 		     sizeof(struct ffa_composite_memory_region) +
 		     sizeof(struct ffa_memory_region_constituent);
@@ -2198,7 +2198,7 @@
 		 * alignment faults.
 		 */
 		composite_offset =
-			sizeof(struct ffa_memory_region) +
+			retrieve_response->receivers_offset +
 			(uint32_t)(receiver_count *
 				   retrieve_response->memory_access_desc_size);
 
@@ -2739,7 +2739,7 @@
 				     struct mpool *page_pool)
 {
 	uint32_t expected_retrieve_request_length =
-		sizeof(struct ffa_memory_region) +
+		retrieve_request->receivers_offset +
 		(uint32_t)(retrieve_request->receiver_count *
 			   retrieve_request->memory_access_desc_size);
 	ffa_memory_handle_t handle = retrieve_request->handle;
diff --git a/vmlib/ffa.c b/vmlib/ffa.c
index 6c85ec3..a92c3b3 100644
--- a/vmlib/ffa.c
+++ b/vmlib/ffa.c
@@ -97,8 +97,7 @@
 	memory_region->tag = tag;
 	memory_region->memory_access_desc_size = receiver_desc_size;
 	memory_region->receiver_count = receiver_count;
-	memory_region->receivers_offset =
-		offsetof(struct ffa_memory_region, receivers);
+	memory_region->receivers_offset = sizeof(struct ffa_memory_region);
 #if defined(__linux__) && defined(__KERNEL__)
 	memset(memory_region->reserved, 0, sizeof(memory_region->reserved));
 #else
@@ -139,7 +138,7 @@
 	 * structure should point to the same offset value.
 	 */
 	composite_memory_region_offset =
-		sizeof(struct ffa_memory_region) +
+		memory_region->receivers_offset +
 		memory_region->receiver_count *
 			memory_region->memory_access_desc_size;
 	for (i = 0U; i < memory_region->receiver_count; i++) {
@@ -249,10 +248,10 @@
 				      receiver_desc_size);
 
 #if defined(__linux__) && defined(__KERNEL__)
-	memcpy(memory_region->receivers, receivers,
+	memcpy(ffa_memory_region_get_receiver(memory_region, 0), receivers,
 	       receiver_count * memory_region->memory_access_desc_size);
 #else
-	memcpy_s(memory_region->receivers,
+	memcpy_s(ffa_memory_region_get_receiver(memory_region, 0),
 		 MAX_MEM_SHARE_RECIPIENTS *
 			 memory_region->memory_access_desc_size,
 		 receivers,
@@ -311,10 +310,10 @@
 				      receiver_desc_size);
 
 #if defined(__linux__) && defined(__KERNEL__)
-	memcpy(memory_region->receivers, receivers,
+	memcpy(ffa_memory_region_get_receiver(memory_region, 0), receivers,
 	       receiver_count * memory_region->memory_access_desc_size);
 #else
-	memcpy_s(memory_region->receivers,
+	memcpy_s(ffa_memory_region_get_receiver(memory_region, 0),
 		 MAX_MEM_SHARE_RECIPIENTS *
 			 memory_region->memory_access_desc_size,
 		 receivers,
@@ -329,7 +328,7 @@
 		receiver->composite_memory_region_offset = 0U;
 	}
 
-	return sizeof(struct ffa_memory_region) +
+	return memory_region->receivers_offset +
 	       memory_region->receiver_count *
 		       memory_region->memory_access_desc_size;
 }