Skip to content

Commit 39a15f5

Browse files
jamieNguyenNVIDIAjacobmartin0
authored andcommitted
firmware: arm_ffa: Honor partition info descriptor size
BugLink: https://bugs.launchpad.net/bugs/2154045 FFA_PARTITION_INFO_GET_REGS reports the size of each partition information descriptor in x2[63:48]. However, __ffa_partition_info_get_regs() walks the returned register payload with a hardcoded 24-byte stride (regs += 3), even though the size is already read into buf_sz. That works for the FF-A v1.1/v1.2 24-byte descriptor layout, where each descriptor consumes three registers. Newer FF-A revisions can extend the descriptor while keeping the existing fields at the front. For example, a 48-byte descriptor consumes six registers, so advancing by only three registers desynchronises the parser and can make it read subsequent entries from the middle of a descriptor. Use the advertised descriptor size to derive the register stride. Validate that the size is register-aligned, large enough for the fields parsed by the driver, and that the requested number of descriptors fits in the returned x3..x17 register window. The driver still copies only the fields it understands, but now skips over any trailing descriptor fields correctly. Fixes: ba85c64 ("firmware: arm_ffa: Add support for FFA_PARTITION_INFO_GET_REGS") Suggested-by: Sudeep Holla <sudeep.holla@kernel.org> Signed-off-by: Jamie Nguyen <jamien@nvidia.com> Link: https://patch.msgid.link/20260518203116.42624-1-jamien@nvidia.com (sudeep.holla: Minor rewordng of the commit message and subject) Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org> (backported from commit 01b9cae linux-next) Signed-off-by: Jamie Nguyen <jamien@nvidia.com> Acked-by: Nirmoy Das <nirmoyd@nvidia.com> Acked-by: Seth Forshee <sforshee@nvidia.com> Acked-by: Carol L Soto <csoto@nvidia.com> Signed-off-by: Brad Figg <bfigg@nvidia.com>
1 parent ebf2be6 commit 39a15f5

1 file changed

Lines changed: 16 additions & 11 deletions

File tree

drivers/firmware/arm_ffa/driver.c

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -323,11 +323,9 @@ __ffa_partition_info_get(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
323323
#define PART_INFO_EXEC_CXT_MASK GENMASK(31, 16)
324324
#define PART_INFO_PROPS_MASK GENMASK(63, 32)
325325
#define FFA_PART_INFO_GET_REGS_FIRST_REG 3
326-
#define FFA_PART_INFO_GET_REGS_REGS_PER_DESC 3
327-
#define FFA_PART_INFO_GET_REGS_MAX_DESC \
328-
(((sizeof(ffa_value_t) / sizeof_field(ffa_value_t, a0)) - \
329-
FFA_PART_INFO_GET_REGS_FIRST_REG) / \
330-
FFA_PART_INFO_GET_REGS_REGS_PER_DESC)
326+
#define FFA_PART_INFO_GET_REGS_MIN_REGS_PER_DESC 3
327+
#define FFA_PART_INFO_GET_REGS_NUM_REGS \
328+
(sizeof(ffa_value_t) / sizeof_field(ffa_value_t, a0))
331329
#define PART_INFO_ID(x) ((u16)(FIELD_GET(PART_INFO_ID_MASK, (x))))
332330
#define PART_INFO_EXEC_CXT(x) ((u16)(FIELD_GET(PART_INFO_EXEC_CXT_MASK, (x))))
333331
#define PART_INFO_PROPERTIES(x) ((u32)(FIELD_GET(PART_INFO_PROPS_MASK, (x))))
@@ -341,7 +339,7 @@ __ffa_partition_info_get_regs(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
341339

342340
do {
343341
__le64 *regs;
344-
int idx, nr_desc, buf_idx;
342+
int idx, nr_desc, buf_idx, regs_per_desc, max_desc;
345343

346344
invoke_ffa_fn((ffa_value_t){
347345
.a0 = FFA_PARTITION_INFO_GET_REGS,
@@ -364,18 +362,25 @@ __ffa_partition_info_get_regs(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
364362
if (cur_idx < start_idx || cur_idx >= count)
365363
return -EINVAL;
366364

365+
buf_sz = PARTITION_INFO_SZ(partition_info.a2);
366+
if (buf_sz % sizeof(*regs))
367+
return -EINVAL;
368+
369+
regs_per_desc = buf_sz / sizeof(*regs);
370+
if (regs_per_desc < FFA_PART_INFO_GET_REGS_MIN_REGS_PER_DESC)
371+
return -EINVAL;
372+
367373
nr_desc = cur_idx - start_idx + 1;
368-
if (nr_desc > FFA_PART_INFO_GET_REGS_MAX_DESC)
374+
max_desc = (FFA_PART_INFO_GET_REGS_NUM_REGS -
375+
FFA_PART_INFO_GET_REGS_FIRST_REG) / regs_per_desc;
376+
if (nr_desc > max_desc)
369377
return -EINVAL;
370378

371379
buf_idx = buf - buffer;
372380
if (buf_idx + nr_desc > num_parts)
373381
return -EINVAL;
374382

375383
tag = UUID_INFO_TAG(partition_info.a2);
376-
buf_sz = PARTITION_INFO_SZ(partition_info.a2);
377-
if (buf_sz > sizeof(*buffer))
378-
buf_sz = sizeof(*buffer);
379384

380385
regs = (void *)&partition_info.a3;
381386
for (idx = 0; idx < nr_desc; idx++, buf++) {
@@ -394,7 +399,7 @@ __ffa_partition_info_get_regs(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
394399
buf->exec_ctxt = PART_INFO_EXEC_CXT(val);
395400
buf->properties = PART_INFO_PROPERTIES(val);
396401
uuid_copy(&buf->uuid, &uuid_regs.uuid);
397-
regs += 3;
402+
regs += regs_per_desc;
398403
}
399404
start_idx = cur_idx + 1;
400405

0 commit comments

Comments
 (0)