In qcom_pas_segment_dump() and qcom_pas_da_to_va(), the offset calculation results are stored in signed 32-bit integers (total_offset and offset). On 64-bit architectures, this can truncate the 64-bit address arithmetic result if the subtraction or addition exceeds 2GB, causing erroneous bounds check failures or invalid pointer translations.
Fix this by using unsigned size_t offsets and explicit comparison-based bounds checking. Check that the address is above the base before subtracting, and use the form (len > mem_size - offset) instead of (offset + len > mem_size) to avoid unsigned overflow. Signed-off-by: Anup Vishwakarma <[email protected]> --- drivers/remoteproc/qcom_q6v5_pas.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c index a005546c265d..c95a030949d7 100644 --- a/drivers/remoteproc/qcom_q6v5_pas.c +++ b/drivers/remoteproc/qcom_q6v5_pas.c @@ -130,10 +130,19 @@ static void qcom_pas_segment_dump(struct rproc *rproc, void *dest, size_t offset, size_t size) { struct qcom_pas *pas = rproc->priv; - int total_offset; + u64 addr = segment->da + segment->offset + offset; + size_t total_offset; - total_offset = segment->da + segment->offset + offset - pas->mem_phys; - if (total_offset < 0 || total_offset + size > pas->mem_size) { + if (addr < pas->mem_phys) { + dev_err(pas->dev, + "invalid copy request for segment %pad with offset %zu and size %zu)\n", + &segment->da, offset, size); + memset(dest, 0xff, size); + return; + } + + total_offset = addr - pas->mem_phys; + if (total_offset > pas->mem_size || size > pas->mem_size - total_offset) { dev_err(pas->dev, "invalid copy request for segment %pad with offset %zu and size %zu)\n", &segment->da, offset, size); @@ -445,10 +454,13 @@ static int qcom_pas_stop(struct rproc *rproc) static void *qcom_pas_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem) { struct qcom_pas *pas = rproc->priv; - int offset; + size_t offset; + + if (da < pas->mem_reloc) + return NULL; offset = da - pas->mem_reloc; - if (offset < 0 || offset + len > pas->mem_size) + if (offset > pas->mem_size || len > pas->mem_size - offset) return NULL; if (is_iomem) -- 2.43.0

