On Mon, Aug 03, 2026 at 05:13:31PM +0530, Mukesh Ojha wrote:
> 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.
> 

Fixes: fd2c15ec1dd3 ("remoteproc: resource table overhaul")

Regards,
Bjorn

> Signed-off-by: Mukesh Ojha <[email protected]>
> ---
>  include/linux/rsc_table.h | 17 +++++++++++------
>  1 file changed, 11 insertions(+), 6 deletions(-)
> 
> diff --git a/include/linux/rsc_table.h b/include/linux/rsc_table.h
> index 0ad9122c22af..71b60125310e 100644
> --- a/include/linux/rsc_table.h
> +++ b/include/linux/rsc_table.h
> @@ -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;
> -- 
> 2.53.0
> 

Reply via email to