⬢ DragonFlyBSD Kernel Audit
DF-3697 / fix.diff
← back to finding ↓ download raw
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);