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;
}