mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 01:08:13 -04:00
firmware: arm_ffa: Fix Endpoint Memory Access Descriptor offset calculation
Use the descriptor's `ep_mem_offset` to calculate the start of the endpoint
memory access array and to comply with the FF-A spec instead of defaulting
to `sizeof(struct ffa_mem_region)`.
This requires moving `ffa_mem_region_additional_setup()` earlier in the setup
flow.
Also, add sanity checks to ensure the calculated descriptor offsets do not
exceed `max_fragsize`.
Fixes: 113580530e ("firmware: arm_ffa: Update memory descriptor to support v1.1 format")
Reviewed-by: Sudeep Holla <sudeep.holla@kernel.org>
Signed-off-by: Mostafa Saleh <smostafa@google.com>
Signed-off-by: Sebastian Ene <sebastianene@google.com>
Link: https://patch.msgid.link/20260702103848.1647249-3-sebastianene@google.com
Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
committed by
Marc Zyngier
parent
3383ffb7ef
commit
b4d961351a
@@ -685,19 +685,30 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
|
||||
struct ffa_composite_mem_region *composite;
|
||||
struct ffa_mem_region_addr_range *constituents;
|
||||
struct ffa_mem_region_attributes *ep_mem_access;
|
||||
u32 idx, frag_len, length, buf_sz = 0, num_entries = sg_nents(args->sg);
|
||||
u32 idx, frag_len, length, buf_sz = 0, num_entries = sg_nents(args->sg), ep_offset;
|
||||
u32 emad_end, emad_size = ffa_emad_size_get(drv_info->version);
|
||||
|
||||
mem_region->tag = args->tag;
|
||||
mem_region->flags = args->flags;
|
||||
mem_region->sender_id = drv_info->vm_id;
|
||||
mem_region->attributes = ffa_memory_attributes_get(func_id);
|
||||
|
||||
ffa_mem_region_additional_setup(drv_info->version, mem_region);
|
||||
composite_offset = ffa_mem_desc_offset(buffer, args->nattrs,
|
||||
drv_info->version);
|
||||
if (composite_offset + sizeof(*composite) > max_fragsize)
|
||||
return -ENXIO;
|
||||
|
||||
for (idx = 0; idx < args->nattrs; idx++) {
|
||||
ep_mem_access = buffer +
|
||||
ffa_mem_desc_offset(buffer, idx, drv_info->version);
|
||||
memset(ep_mem_access, 0, ffa_emad_size_get(drv_info->version));
|
||||
ep_offset = ffa_mem_desc_offset(buffer, idx, drv_info->version);
|
||||
if (check_add_overflow(ep_offset, emad_size, &emad_end))
|
||||
return -ENXIO;
|
||||
|
||||
if (emad_end > max_fragsize)
|
||||
return -ENXIO;
|
||||
|
||||
ep_mem_access = buffer + ep_offset;
|
||||
memset(ep_mem_access, 0, emad_size);
|
||||
ep_mem_access->receiver = args->attrs[idx].receiver;
|
||||
ep_mem_access->attrs = args->attrs[idx].attrs;
|
||||
ep_mem_access->composite_off = composite_offset;
|
||||
@@ -707,7 +718,6 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
|
||||
}
|
||||
mem_region->handle = 0;
|
||||
mem_region->ep_count = args->nattrs;
|
||||
ffa_mem_region_additional_setup(drv_info->version, mem_region);
|
||||
|
||||
composite = buffer + composite_offset;
|
||||
composite->total_pg_cnt = ffa_get_num_pages_sg(args->sg);
|
||||
|
||||
@@ -452,7 +452,7 @@ ffa_mem_desc_offset(struct ffa_mem_region *buf, int count, u32 ffa_version)
|
||||
if (!FFA_MEM_REGION_HAS_EP_MEM_OFFSET(ffa_version))
|
||||
offset += offsetof(struct ffa_mem_region, ep_mem_offset);
|
||||
else
|
||||
offset += sizeof(struct ffa_mem_region);
|
||||
offset += buf->ep_mem_offset;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user