DF-3697 / fix.diff
diff --git a/sys/dev/drm/amd/amdgpu/gfx_v9_0.c b/sys/dev/drm/amd/amdgpu/gfx_v9_0.c index 1111111..2222222 100644 --- a/sys/dev/drm/amd/amdgpu/gfx_v9_0.c +++ b/sys/dev/drm/amd/amdgpu/gfx_v9_0.c @@ -513,11 +513,24 @@ static void gfx_v9_0_free_microcode(struct amdgpu_device *adev) kfree(adev->gfx.rlc.register_list_format); } -static void gfx_v9_0_init_rlc_ext_microcode(struct amdgpu_device *adev) +static int gfx_v9_0_init_rlc_ext_microcode(struct amdgpu_device *adev) { const struct rlc_firmware_header_v2_1 *rlc_hdr; + const struct amdgpu_firmware *fw = adev->gfx.rlc_fw; + u32 offset, size; rlc_hdr = (const struct rlc_firmware_header_v2_1 *)adev->gfx.rlc_fw->data; + + /* the v2_1 save-restore-list blobs must lie inside the image */ +#define CHECK_V2_1_RANGE(off_field, size_field) do { \ + offset = le32_to_cpu(rlc_hdr->off_field); \ + size = le32_to_cpu(rlc_hdr->size_field); \ + if (offset > fw->datasize || size > fw->datasize - offset) { \ + dev_err(adev->dev, "gfx9: invalid RLC v2_1 " #off_field "\n"); \ + return -EINVAL; \ + } \ +} while (0) + CHECK_V2_1_RANGE(save_restore_list_cntl_offset_bytes, save_restore_list_cntl_size_bytes); + CHECK_V2_1_RANGE(save_restore_list_gpm_offset_bytes, save_restore_list_gpm_size_bytes); + CHECK_V2_1_RANGE(save_restore_list_srm_offset_bytes, save_restore_list_srm_size_bytes); adev->gfx.rlc_srlc_fw_version = le32_to_cpu(rlc_hdr->save_restore_list_cntl_ucode_ver); adev->gfx.rlc_srlc_feature_version = le32_to_cpu(rlc_hdr->save_restore_list_cntl_feature_ver); adev->gfx.rlc.save_restore_list_cntl_size_bytes = le32_to_cpu(rlc_hdr->save_restore_list_cntl_size_bytes); @@ -535,6 +548,7 @@ static void gfx_v9_0_init_rlc_ext_microcode(struct amdgpu_device *adev) adev->gfx.rlc.reg_list_format_direct_reg_list_length = le32_to_cpu(rlc_hdr->reg_list_format_direct_reg_list_length); + return 0; } static void gfx_v9_0_check_fw_write_wait(struct amdgpu_device *adev) @@ -712,7 +726,10 @@ static int gfx_v9_0_init_microcode(struct amdgpu_device *adev) adev->gfx.rlc.register_restore[i] = le32_to_cpu(tmp[i]); if (adev->gfx.rlc.is_rlc_v2_1) - gfx_v9_0_init_rlc_ext_microcode(adev); + err = gfx_v9_0_init_rlc_ext_microcode(adev); + if (err) + goto out; snprintf(fw_name, sizeof(fw_name), "amdgpufw_%s_mec", chip_name); |