[PATCH v3 1/2] firmware: arm_ffa: Fix Endpoint Memory Access Descriptor offset calculation

Sudeep Holla sudeep.holla at kernel.org
Wed May 13 10:19:39 PDT 2026


On Wed, May 13, 2026 at 01:34:42PM +0000, Mostafa Saleh wrote:
> On Tue, May 12, 2026 at 12:44:41PM +0000, Sebastian Ene wrote:
> > 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`.
> > 
> > Signed-off-by: Sebastian Ene <sebastianene at google.com>
> > ---
> >  drivers/firmware/arm_ffa/driver.c | 14 ++++++++++----
> >  include/linux/arm_ffa.h           |  2 +-
> >  2 files changed, 11 insertions(+), 5 deletions(-)
> > 
> > diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
> > index eb2782848283..56b166290b24 100644
> > --- a/drivers/firmware/arm_ffa/driver.c
> > +++ b/drivers/firmware/arm_ffa/driver.c
> > @@ -685,18 +685,25 @@ 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;
> >  
> >  	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 > max_fragsize - sizeof(struct ffa_composite_mem_region))
> > +		return -ENXIO;
> 
> nit: This driver seems to use sizeof() with variable name rather than
> type (except for one place) so it may be good to keep that.
> 

Agreed, +1.

> >  
> >  	for (idx = 0; idx < args->nattrs; idx++) {
> > -		ep_mem_access = buffer +
> > -			ffa_mem_desc_offset(buffer, idx, drv_info->version);
> > +		ep_offset = ffa_mem_desc_offset(buffer, idx, drv_info->version);
> > +		if (ep_offset > max_fragsize - sizeof(struct ffa_mem_region_attributes))
> > +			return -ENXIO;
> > +
> > +		ep_mem_access = buffer + ep_offset;
> >  		ep_mem_access->receiver = args->attrs[idx].receiver;
> >  		ep_mem_access->attrs = args->attrs[idx].attrs;
> >  		ep_mem_access->composite_off = composite_offset;
> > @@ -708,7 +715,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);
> > diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h
> > index 81e603839c4a..62d67dae8b70 100644
> > --- a/include/linux/arm_ffa.h
> > +++ b/include/linux/arm_ffa.h
> > @@ -445,7 +445,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;
> 
> Does it make sense to also set buf->ep_mem_offset for the other
> case in ffa_mem_region_additional_setup() and then add this
> unconditionally here?
> 

I need to cross-check the spec, but if I vaguely recall as the name
FFA_MEM_REGION_HAS_EP_MEM_OFFSET suggests, older versions don't have that
field to use it.

-- 
Regards,
Sudeep



More information about the linux-arm-kernel mailing list