Re: [PATCH] remoteproc: imx_rproc: Fix off-by-one in address translation

[email protected] Thu, 30 Jul 2026 03:21:06 +0000
Newsgroups dev.linux.lists.imx
Message-ID <[email protected]>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

Pre-existing issues:
- [High] The patch fixes an off-by-one boundary check in `imx_rproc_da_to_sys()` using `<=` but misses the identical boundary check in its caller `imx_rproc_da_to_va()`, leaving the bug unresolved.
- [High] An integer overflow in the memory segment bounds checks allows untrusted firmware to perform arbitrary out-of-bounds kernel writes on 64-bit platforms.
--

--- Patch [1]: [PATCH] remoteproc: imx_rproc: Fix off-by-one in address translation ---
commit 26c9a9508d8034f3f59181045a1d03a59fa5b603
Author: Peng Fan <[email protected]>

remoteproc: imx_rproc: Fix off-by-one in address translation

This commit fixes an off-by-one error in imx_rproc_da_to_sys() by changing a
strict less-than comparison to a less-than-or-equal comparison for firmware
segments that exactly fill a memory region.

Link: https://lore.kernel.org/all/[email protected]/

> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
> index 745ce52cd8226..9af0aa26ce9b7 100644
> --- a/drivers/remoteproc/imx_rproc.c
> +++ b/drivers/remoteproc/imx_rproc.c
> @@ -552,7 +552,7 @@ static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da,
>  				continue;
>  		}
>  
> -		if (da >= att->da && da + len < att->da + att->size) {
> +		if (da >= att->da && da + len <= att->da + att->size) {

[Severity: High]
This is a pre-existing issue, but does this fix actually solve the problem
since the caller still uses a strict less-than check?

When imx_rproc_da_to_sys() successfully translates a valid boundary case
where da + len == att->da + att->size, its caller imx_rproc_da_to_va() performs
a secondary boundary check:

drivers/remoteproc/imx_rproc.c:imx_rproc_da_to_va() {
    ...
    if (imx_rproc_da_to_sys(priv, da, len, &sys, is_iomem))
        return NULL;

    for (i = 0; i < IMX_RPROC_MEM_MAX; i++) {
        if (sys >= priv->mem[i].sys_addr && sys + len <
            priv->mem[i].sys_addr +  priv->mem[i].size) {
            ...
        }
    }
    ...
}

Because imx_rproc_da_to_va() still uses a strict less-than comparison (<)
instead of (<=), won't it still reject the exactly matching segment and
return NULL, preventing the system from booting valid firmware?


[Severity: High]
This is also a pre-existing issue, but can the da + len calculation overflow
64-bit integers on 64-bit platforms?

In rproc_elf_load_segments() from drivers/remoteproc/remoteproc_elf_loader.c,
da and memsz (len) are extracted from the ELF headers. By providing a
maliciously crafted da (e.g., 0x10000000) and a massive memsz
(e.g., 0xFFFFFFFFF0000000), da + len can overflow and wrap around to a small
value (e.g., 0).

Could this bypass the primary bounds check here:

    if (da >= att->da && da + len <= att->da + att->size) {

and the secondary check in imx_rproc_da_to_va():

    if (sys >= priv->mem[i].sys_addr && sys + len < ...

allowing untrusted firmware to perform arbitrary out-of-bounds kernel memory
writes during memcpy() in rproc_elf_load_segments()?

>  			unsigned int offset = da - att->da;
>  
>  			*sys = att->sa + offset;

-- 
Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=1