remoteproc: fix OOB read via signed offset in rsc_table_for_each_entry()

table->offset[i] is a u32 from firmware, but was stored into a signed
int.  A crafted offset like 0xFFFFFFF0 becomes -16, placing hdr 16 bytes
before the table buffer.  The subsequent avail check was bypassed
because the negative int was promoted to a large size_t in the
expression "table_sz - offset - sizeof(*hdr)", yielding a large positive
avail and letting the out-of-bounds hdr->type read proceed undetected.

Store the offset as u32 and validate it with unsigned comparisons before
any pointer arithmetic.

Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
Fixes: fd2c15ec1d ("remoteproc: resource table overhaul")
Link: https://lore.kernel.org/r/20260803114331.3277263-6-mukesh.ojha@oss.qualcomm.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
This commit is contained in:
Mukesh Ojha
2026-08-03 17:13:31 +05:30
committed by Bjorn Andersson
parent bf9053b22c
commit bb840ea693

View File

@@ -310,17 +310,22 @@ static inline int rsc_table_for_each_entry(struct resource_table *table,
int i, ret;
for (i = 0; i < table->num; i++) {
int offset = table->offset[i];
struct fw_rsc_hdr *hdr = (void *)table + offset;
int avail = table_sz - offset - sizeof(*hdr);
int rsc_offset = offset + sizeof(*hdr);
void *rsc = (void *)hdr + sizeof(*hdr);
u32 offset = table->offset[i];
struct fw_rsc_hdr *hdr;
int avail, rsc_offset;
void *rsc;
if (avail < 0) {
if (offset < sizeof(*table) || offset >= table_sz ||
table_sz - offset < sizeof(*hdr)) {
dev_err(dev, "rsc table is truncated\n");
return -EINVAL;
}
hdr = (void *)table + offset;
avail = table_sz - offset - sizeof(*hdr);
rsc_offset = offset + sizeof(*hdr);
rsc = (void *)hdr + sizeof(*hdr);
ret = cb(hdr->type, rsc, rsc_offset, avail, data);
if (ret)
return ret;