amdxdna_drm_sync_bo_ioctl() forms the range for a device BO by adding the
caller's offset and size to the BO address without checking either, while
amdxdna_flush_bo() one call down guards the same arithmetic with
check_add_overflow().

A size that wraps flush_end leaves it below the heap it is clamped
against, so every heap fails the start >= end test, and a sync that asked
for more than the address space holds reports success having flushed
nothing. Reject it instead.

Signed-off-by: Taimuraz Kaitmazov <[email protected]>
---
 drivers/accel/amdxdna/amdxdna_gem.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/accel/amdxdna/amdxdna_gem.c 
b/drivers/accel/amdxdna/amdxdna_gem.c
index 7df4bbb16..d944f1b99 100644
--- a/drivers/accel/amdxdna/amdxdna_gem.c
+++ b/drivers/accel/amdxdna/amdxdna_gem.c
@@ -1287,8 +1287,13 @@ int amdxdna_drm_sync_bo_ioctl(struct drm_device *dev,
                struct amdxdna_gem_obj *heap;
                unsigned long heap_id;
                u64 bo_start = amdxdna_gem_dev_addr(abo);
-               u64 flush_start = bo_start + args->offset;
-               u64 flush_end = flush_start + args->size;
+               u64 flush_start, flush_end;
+
+               if (check_add_overflow(bo_start, args->offset, &flush_start) ||
+                   check_add_overflow(flush_start, args->size, &flush_end)) {
+                       ret = -EINVAL;
+                       goto put_obj;
+               }
 
                xa_for_each_range(&client->dev_heap_xa, heap_id, heap,
                                  abo->heap_start_id, abo->heap_end_id) {
-- 
2.55.0

Reply via email to