[PATCH v5 2/6] firmware: arm_ffa: Fix out-of-bound writes in ffa_setup_and_transmit()

From: Mostafa Saleh

Date: Tue May 26 2026 - 11:29:19 EST


Sashiko (locally) reports multiple out-of-bound issues in
ffa_setup_and_transmit:
1) Writing ep_mem_access->reserved can write out of bounds for FFA
versions < 1.2 as ffa_emad_size_get() returns 16 bytes in that case
while reserved has an offset of 24.
Instead of zeroing fields, memset the struct to zero first based on
the FFA version.

2) Make sure there is enough size to write constituents.

While at it, convert the only sizeof() in the driver that uses a
type instead of variable.

Reviewed-by: Sudeep Holla <sudeep.holla@xxxxxxxxxx>
Signed-off-by: Mostafa Saleh <smostafa@xxxxxxxxxx>
---
drivers/firmware/arm_ffa/driver.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index b9f17fda7243..059e2aae7ca0 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -715,11 +715,10 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
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_mem_access->receiver = args->attrs[idx].receiver;
ep_mem_access->attrs = args->attrs[idx].attrs;
ep_mem_access->composite_off = composite_offset;
- ep_mem_access->flag = 0;
- ep_mem_access->reserved = 0;
ffa_emad_impdef_value_init(drv_info->version,
ep_mem_access->impdef_val,
args->attrs[idx].impdef_val);
@@ -759,7 +758,7 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
constituents = buffer;
}

- if ((void *)constituents - buffer > max_fragsize) {
+ if ((void *)constituents + sizeof(*constituents) - buffer > max_fragsize) {
pr_err("Memory Region Fragment > Tx Buffer size\n");
return -EFAULT;
}
@@ -768,7 +767,7 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
constituents->pg_cnt = args->sg->length / FFA_PAGE_SIZE;
constituents->reserved = 0;
constituents++;
- frag_len += sizeof(struct ffa_mem_region_addr_range);
+ frag_len += sizeof(*constituents);
} while ((args->sg = sg_next(args->sg)));

return ffa_transmit_fragment(func_id, addr, buf_sz, frag_len,
--
2.54.0.746.g67dd491aae-goog