diff --git a/sys/dev/drm/radeon/si_smc.c b/sys/dev/drm/radeon/si_smc.c --- a/sys/dev/drm/radeon/si_smc.c +++ b/sys/dev/drm/radeon/si_smc.c @@ -258,6 +258,27 @@ src = (const u8 *)rdev->smc_fw->data; } + /* Validate firmware-derived offsets/sizes against the blob and the SMC + * SRAM limit before the write loop, to prevent heap OOB reads + * (offset+size > datasize) and unbounded SMC SRAM writes + * (start+size > limit). This makes the previously-dead `limit` + * parameter actually bound the write, matching the bounds checks in + * si_copy_bytes_to_smc() and si_set_smc_sram_address(). + */ + if (rdev->new_fw) { + const struct smc_firmware_header_v1_0 *hdr = + (const struct smc_firmware_header_v1_0 *)rdev->smc_fw->data; + + if (le32_to_cpu(hdr->header.ucode_array_offset_bytes) + ucode_size > + rdev->smc_fw->datasize) { + DRM_ERROR("SMC ucode read exceeds firmware blob size\n"); + return -EINVAL; + } + } + if ((uint64_t)ucode_start_address + ucode_size > limit) { + DRM_ERROR("SMC ucode write exceeds SRAM limit\n"); + return -EINVAL; + } if (ucode_size & 3) return -EINVAL;