diff --git a/sys/dev/drm/amd/amdgpu/amdgpu_gart.c b/sys/dev/drm/amd/amdgpu/amdgpu_gart.c --- a/sys/dev/drm/amd/amdgpu/amdgpu_gart.c +++ b/sys/dev/drm/amd/amdgpu/amdgpu_gart.c @@ -116,7 +116,16 @@ struct amdgpu_bo_param bp; memset(&bp, 0, sizeof(bp)); - bp.size = adev->gart.table_size; + /* Validate table_size against num_gpu_pages: a wrapped 32-bit multiply + * in gmc_v{7,8,9}_0_gart_init would allocate a far-too-small BO and + * amdgpu_gart_bind/unbind would write PTEs past it. */ + if (adev->gart.num_gpu_pages == 0 || + adev->gart.table_size < adev->gart.num_gpu_pages * sizeof(uint64_t)) { + dev_err(adev->dev, "GART table_size %u too small for %u pages\n", + adev->gart.table_size, adev->gart.num_gpu_pages); + return -EOVERFLOW; + } + bp.size = adev->gart.table_size; bp.byte_align = PAGE_SIZE; bp.domain = AMDGPU_GEM_DOMAIN_VRAM; bp.flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | @@ -355,6 +364,12 @@ DRM_ERROR("Page size is smaller than GPU page size!\n"); return -EINVAL; } + /* Reject gart_size whose page count overflows the unsigned int fields. */ + if (adev->gmc.gart_size > (uint64_t)UINT_MAX * AMDGPU_GPU_PAGE_SIZE) { + DRM_ERROR("GART size %llu too large for 32-bit page count\n", + (unsigned long long)adev->gmc.gart_size); + return -EOVERFLOW; + } r = amdgpu_gart_dummy_page_init(adev); if (r) return r;