remoteproc: core: fix integer overflow in rproc_da_to_va() bounds check
PATCH 1/1 remoteproc: core: fix integer overflow in rproc_da_to_va() bounds check
offset is calculated as da - carveout->da and stored in a 32 bit signed int, while da and carveout->da 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 > carveout->len can itself overflow when offset and len are both large, providing a second bypass.
Rewrite the bounds check entirely in u64 arithmetic. Reject underflow before computing offset (da < carveout->da). Replace the addition-based overflow check with a subtraction-based one (len > carveout->len - offset) so no intermediate sum can wrap.
--- drivers/remoteproc/remoteproc_core.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/remoteproc/remoteproc_core.c +6 -4
@@ -198,18 +198,20 @@ void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem) }list_for_each_entry (carveout, &rproc->carveouts, node) { -int offset = da - carveout->da; +u64 offset;/* Verify that carveout is allocated */ if (!carveout->va)continue ;/* try next carveout if da is too small */ -if (offset <0 ) +if (da < carveout->da)continue ; -/* try next carveout if da is too large */ -if (offset + len > carveout->len) + offset = da - carveout->da; + +/* try next carveout if da or len is too large */ +if (offset > carveout->len || len > carveout->len - offset)continue ; ptr = carveout->va + offset;
Signature · 1 line
2.43.0
Quoted 13 lines · Atul Akella
offset is calculated as da -
carveout->daand stored in a 32 bit signed int, while da andcarveout->daare 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 >carveout->lencan itself overflow when offset and len are both large, providing a second bypass.Rewrite the bounds check entirely in u64 arithmetic. Reject underflow before computing offset (da <
carveout->da). Replace the addition-based overflow check with a subtraction-based one (len >carveout->len- offset) so no intermediate sum can wrap.
Quoted 5 lines
Signed-off-by Atul Akella <[email protected]>--- drivers/remoteproc/remoteproc_core.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
Applied.
Thanks,
Mathieu
Quoted 32 lines
drivers/remoteproc/remoteproc_core.c +6
-4@@ -198,18 +198,20 @@ void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem) }list_for_each_entry (carveout, &rproc->carveouts, node) { -int offset = da - carveout->da; +u64 offset;/* Verify that carveout is allocated */ if (!carveout->va)continue ;/* try next carveout if da is too small */ -if (offset <0 ) +if (da < carveout->da)continue ; -/* try next carveout if da is too large */ -if (offset + len > carveout->len) + offset = da - carveout->da; + +/* try next carveout if da or len is too large */ +if (offset > carveout->len || len > carveout->len - offset)continue ; ptr = carveout->va + offset;Signature · 1 line
2.43.0