[PATCH 4/4] remoteproc: qcom: Fix bounds check in wcnss_da_to_va()

From: Atul Akella

Date: Fri Nov 06 2026 - 13:49:54 EST


offset is calculated as da - wcnss->mem_reloc and stored in a
32 bit signed int, while da and wcnss->mem_reloc are both u64.
For a sufficiently small da, the 64bit difference is truncated
into the 32 bit int, bypassing the offset < 0 underflow check
with a small positive value. Additionally, offset + len >
wcnss->mem_size can itself overflow when offset and len are both
large, providing a second bypass.

da and len come from firmware's ELF program headers via
rproc_da_to_va(), and the result is used by the ELF loader
to write firmware segments, so a malformed firmware image can
cause writes outside the carveout.

Rewrite the bounds check entirely in u64 arithmetic. Reject
underflow before computing offset (da < wcnss->mem_reloc).
Replace the addition based overflow check with a
subtraction based one (len > wcnss->mem_size - offset) so no
intermediate sum can wrap.

Fixes: aed361adca9f ("remoteproc: qcom: Introduce WCNSS peripheral image loader")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Atul Akella <atul.akella@xxxxxxxxx>
---
drivers/remoteproc/qcom_wcnss.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
index c856a92af43c..d95530e8be71 100644
--- a/drivers/remoteproc/qcom_wcnss.c
+++ b/drivers/remoteproc/qcom_wcnss.c
@@ -321,10 +321,12 @@ static int wcnss_stop(struct rproc *rproc)
static void *wcnss_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
{
struct qcom_wcnss *wcnss = rproc->priv;
- int offset;
+ u64 offset;

+ if (da < wcnss->mem_reloc)
+ return NULL;
offset = da - wcnss->mem_reloc;
- if (offset < 0 || offset + len > wcnss->mem_size)
+ if (offset > wcnss->mem_size || len > wcnss->mem_size - offset)
return NULL;

return (__force void *)wcnss->mem_region + offset;
--
2.43.0