[PATCH] drm/amdkfd: fix integer overflow in queue ring buffer size calculation
"Marioukhine, Vladimir" <[email protected]>
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <SA1PR12MB8600EE73548498C578990CF49FDC2@SA1PR12MB8600.namprd12.prod.outlook.com> |
AMD General
queue_size and metadata_queue_size are u64 fields copied directly from
user-supplied ring_size and metadata_ring_size ioctl arguments. When
both are set to 0x8000000000000000 (2^63), their sum overflows to zero
in kfd_queue_acquire_buffers(), causing kfd_queue_buffer_get() to skip
the BO size validation and accept any GPU buffer object regardless of
its actual size. The resulting queue is misconfigured: the kernel
validates only a 4 KB backing GPU buffer while the hardware is
programmed using a ring size derived from the much larger user-controlled
value, potentially resulting in GPU MMU faults and GPU reset.
Use check_add_overflow() to detect the overflow at the arithmetic site
and return -EINVAL if it occurs.
Fixes: c51bb53d5c68 ("drm/amdkfd: Add metadata ring buffer for compute")
Signed-off-by: Vladimir Marioukhine <[email protected]>
---
drivers/gpu/drm/amd/amdkfd/kfd_queue.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
index 25954c2c2d91..52cc022dea36 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
@@ -250,9 +250,15 @@ int kfd_queue_acquire_buffers(struct kfd_process_device *pdd, struct queue_prope
/* metadata_queue_size not supported on GFX7/GFX8 */
expected_queue_size =
PAGE_ALIGN(properties->queue_size / 2);
- else
- expected_queue_size =
- PAGE_ALIGN(properties->queue_size + properties->metadata_queue_size);
+ else {
+ u64 total_size;
+
+ if (check_add_overflow(properties->queue_size,
+ properties->metadata_queue_size,
+ &total_size))
+ return -EINVAL;
+ expected_queue_size = PAGE_ALIGN(total_size);
+ }
vm = drm_priv_to_vm(pdd->drm_priv);
err = amdgpu_bo_reserve(vm->root.bo, false);