Validate the conversion of the DMC firmware size from dwords to bytes
using check_mul_overflow() before calculating the firmware payload size.
Reject zero-length payloads and zero MMIO counts in the DMC firmware
header so malformed firmware is caught early. Also set dmc_fw_size only
after the payload allocation succeeds.
Fixes: eb805623d8b1 ("drm/i915/skl: Add support to load SKL CSR firmware.")
Cc: [email protected]
Assisted-by: Claude-Code:Sonnet-5
Signed-off-by: Dibin Moolakadan Subrahmanian
<[email protected]>
---
drivers/gpu/drm/i915/display/intel_dmc.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c
b/drivers/gpu/drm/i915/display/intel_dmc.c
index 051b721a0895..b06143a607eb 100644
--- a/drivers/gpu/drm/i915/display/intel_dmc.c
+++ b/drivers/gpu/drm/i915/display/intel_dmc.c
@@ -1170,7 +1170,7 @@ static u32 parse_dmc_fw_header(struct intel_dmc *dmc,
}
/* Cache the dmc header info. */
- if (mmio_count > mmio_count_max) {
+ if (!mmio_count || mmio_count > mmio_count_max) {
drm_err(display->drm, "DMC firmware has wrong mmio count %u\n",
mmio_count);
return 0;
}
@@ -1178,7 +1178,17 @@ static u32 parse_dmc_fw_header(struct intel_dmc *dmc,
rem_size -= header_len_bytes;
/* fw_size is in dwords, so multiplied by 4 to convert into bytes. */
- payload_size = dmc_header->fw_size * 4;
+ if (check_mul_overflow(dmc_header->fw_size, 4u, &payload_size)) {
+ drm_err(display->drm, "DMC fw_size too large (%u dwords)\n",
+ dmc_header->fw_size);
+ return 0;
+ }
+
+ if (!payload_size) {
+ drm_err(display->drm, "DMC firmware has empty payload\n");
+ return 0;
+ }
+
if (rem_size < payload_size)
goto error_truncated;
@@ -1237,12 +1247,12 @@ static u32 parse_dmc_fw_header(struct intel_dmc *dmc,
dmc_info->mmio_count = mmio_count;
dmc_info->start_mmioaddr = start_mmioaddr;
- dmc_info->dmc_fw_size = dmc_header->fw_size;
-
dmc_info->payload = kmalloc(payload_size, GFP_KERNEL);
if (!dmc_info->payload)
return 0;
+ dmc_info->dmc_fw_size = dmc_header->fw_size;
+
payload = (u8 *)(dmc_header) + header_len_bytes;
memcpy(dmc_info->payload, payload, payload_size);
--
2.43.0