Intel-GFX Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/2] Add validation for DMC firmware header parsing
@ 2026-09-07 13:50 Dibin Moolakadan Subrahmanian
  2026-09-07 13:50 ` [PATCH v3 1/2] drm/i915/dmc: Add sanity check for DMC load address Dibin Moolakadan Subrahmanian
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Dibin Moolakadan Subrahmanian @ 2026-09-07 13:50 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: mitulkumar.ajitkumar.golani, jani.nikula

The DMC firmware parser does not validate the firmware load address
stored in version 3 headers before it is used by dmc_load_program().

The firmware size conversion from dwords to bytes can overflow while
calculating the payload size.

Fix both by validating the firmware load address against the expected
range and using check_mul_overflow() for the firmware size conversion.

v2:
Added Fixes tag in commit messages for both patches.
v3:
Address Sashiko's parser-hardening review comments in patch 2.

Dibin Moolakadan Subrahmanian (2):
  drm/i915/dmc: Add sanity check for DMC load address
  drm/i915/dmc: Harden DMC firmware payload parsing

 drivers/gpu/drm/i915/display/intel_dmc.c      | 95 ++++++++++++++++---
 drivers/gpu/drm/i915/display/intel_dmc_regs.h | 12 +++
 2 files changed, 93 insertions(+), 14 deletions(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v3 1/2] drm/i915/dmc: Add sanity check for DMC load address
  2026-09-07 13:50 [PATCH v3 0/2] Add validation for DMC firmware header parsing Dibin Moolakadan Subrahmanian
@ 2026-09-07 13:50 ` Dibin Moolakadan Subrahmanian
  2026-09-07 13:50 ` [PATCH v3 2/2] drm/i915/dmc: Harden DMC firmware payload parsing Dibin Moolakadan Subrahmanian
  2026-09-07 16:01 ` ✓ i915.CI.BAT: success for Add validation for DMC firmware header parsing (rev4) Patchwork
  2 siblings, 0 replies; 5+ messages in thread
From: Dibin Moolakadan Subrahmanian @ 2026-09-07 13:50 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: mitulkumar.ajitkumar.golani, jani.nikula

For DMC firmware header version 3, the firmware load address is stored
in dmc_info->start_mmioaddr and later used by dmc_load_program().

Unlike the MMIO address table, the firmware load address is not
validated. Add a sanity check to ensure it is within the valid range.

BSpec: 69671, 68378
Fixes: 3d5928a168a9 ("drm/i915/xelpd: Pipe A DMC plugging")
Cc: stable@vger.kernel.org
Assisted-by: Claude-Code:Sonnet-5
Signed-off-by: Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dmc.c      | 79 ++++++++++++++++---
 drivers/gpu/drm/i915/display/intel_dmc_regs.h | 12 +++
 2 files changed, 80 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c
index a191eee240d9..051b721a0895 100644
--- a/drivers/gpu/drm/i915/display/intel_dmc.c
+++ b/drivers/gpu/drm/i915/display/intel_dmc.c
@@ -1023,6 +1023,56 @@ static void dmc_set_fw_offset(struct intel_dmc *dmc,
 	}
 }
 
+/*
+ * Check if the load address is within the valid range for the given DMC ID.
+ */
+static bool dmc_load_addr_sanity_check(struct intel_dmc *dmc,
+				       u32 start_addr, u32 payload_size,
+				       int header_ver, enum intel_dmc_id dmc_id)
+{
+	struct intel_display *display = dmc->display;
+	u32 start_range, end_range, end_addr;
+
+	if (header_ver != 3)
+		return true;
+
+	switch (dmc_id) {
+	case DMC_FW_MAIN:
+		start_range = DMC_MAIN_PROGRAM_BASE_START;
+		end_range = DMC_MAIN_PROGRAM_BASE_END;
+		break;
+	case DMC_FW_PIPEA:
+		start_range = DMC_PIPEA_PROGRAM_BASE_START;
+		end_range = DMC_PIPEA_PROGRAM_BASE_END;
+		break;
+	case DMC_FW_PIPEB:
+		start_range = DMC_PIPEB_PROGRAM_BASE_START;
+		end_range = DMC_PIPEB_PROGRAM_BASE_END;
+		break;
+	case DMC_FW_PIPEC:
+		start_range = DMC_PIPEC_PROGRAM_BASE_START;
+		end_range = DMC_PIPEC_PROGRAM_BASE_END;
+		break;
+	case DMC_FW_PIPED:
+		start_range = DMC_PIPED_PROGRAM_BASE_START;
+		end_range = DMC_PIPED_PROGRAM_BASE_END;
+		break;
+	default:
+		drm_warn(display->drm, "Unknown dmc_id %d for load address sanity check\n", dmc_id);
+		return false;
+	}
+
+	if (payload_size == 0)
+		end_addr = start_addr;
+	else if (check_add_overflow(start_addr, payload_size - 1, &end_addr))
+		return false;
+
+	if (start_addr < start_range || end_addr > end_range)
+		return false;
+
+	return true;
+}
+
 static bool dmc_mmio_addr_sanity_check(struct intel_dmc *dmc,
 				       const u32 *mmioaddr, u32 mmio_count,
 				       int header_ver, enum intel_dmc_id dmc_id)
@@ -1125,6 +1175,24 @@ static u32 parse_dmc_fw_header(struct intel_dmc *dmc,
 		return 0;
 	}
 
+	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 (rem_size < payload_size)
+		goto error_truncated;
+
+	if (payload_size > dmc->max_fw_size) {
+		drm_err(display->drm, "DMC FW too big (%u bytes)\n", payload_size);
+		return 0;
+	}
+
+	if (!dmc_load_addr_sanity_check(dmc, start_mmioaddr, payload_size,
+					dmc_header->header_ver, dmc_id)) {
+		drm_err(display->drm, "DMC %d: firmware has wrong load address\n", dmc_id);
+		return 0;
+	}
+
 	if (!dmc_mmio_addr_sanity_check(dmc, mmioaddr, mmio_count,
 					dmc_header->header_ver, dmc_id)) {
 		drm_err(display->drm, "DMC firmware has Wrong MMIO Addresses\n");
@@ -1169,17 +1237,6 @@ static u32 parse_dmc_fw_header(struct intel_dmc *dmc,
 	dmc_info->mmio_count = mmio_count;
 	dmc_info->start_mmioaddr = start_mmioaddr;
 
-	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 (rem_size < payload_size)
-		goto error_truncated;
-
-	if (payload_size > dmc->max_fw_size) {
-		drm_err(display->drm, "DMC FW too big (%u bytes)\n", payload_size);
-		return 0;
-	}
 	dmc_info->dmc_fw_size = dmc_header->fw_size;
 
 	dmc_info->payload = kmalloc(payload_size, GFP_KERNEL);
diff --git a/drivers/gpu/drm/i915/display/intel_dmc_regs.h b/drivers/gpu/drm/i915/display/intel_dmc_regs.h
index 6b7978fb8986..324320afad58 100644
--- a/drivers/gpu/drm/i915/display/intel_dmc_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_dmc_regs.h
@@ -521,6 +521,18 @@ enum pipedmc_event_id {
 #define TGL_PIPE_MMIO_END(dmc_id)	_PICK_EVEN(((dmc_id) - 1), _TGL_PIPEA_MMIO_END,\
 					      _TGL_PIPEB_MMIO_END)
 
+/* For DMC header version v3*/
+#define DMC_MAIN_PROGRAM_BASE_START	0x80000
+#define DMC_MAIN_PROGRAM_BASE_END	0x86fff
+#define DMC_PIPEA_PROGRAM_BASE_START	0x90000
+#define DMC_PIPEA_PROGRAM_BASE_END	0x96fff
+#define DMC_PIPEB_PROGRAM_BASE_START	0x98000
+#define DMC_PIPEB_PROGRAM_BASE_END	0x9efff
+#define DMC_PIPEC_PROGRAM_BASE_START	0x52000
+#define DMC_PIPEC_PROGRAM_BASE_END	0x53fff
+#define DMC_PIPED_PROGRAM_BASE_START	0x59000
+#define DMC_PIPED_PROGRAM_BASE_END	0x5afff
+
 #define SKL_DMC_DC3_DC5_COUNT	_MMIO(0x80030)
 #define SKL_DMC_DC5_DC6_COUNT	_MMIO(0x8002C)
 #define BXT_DMC_DC3_DC5_COUNT	_MMIO(0x80038)
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v3 2/2] drm/i915/dmc: Harden DMC firmware payload parsing
  2026-09-07 13:50 [PATCH v3 0/2] Add validation for DMC firmware header parsing Dibin Moolakadan Subrahmanian
  2026-09-07 13:50 ` [PATCH v3 1/2] drm/i915/dmc: Add sanity check for DMC load address Dibin Moolakadan Subrahmanian
@ 2026-09-07 13:50 ` Dibin Moolakadan Subrahmanian
  2026-09-07 14:06   ` sashiko-bot
  2026-09-07 16:01 ` ✓ i915.CI.BAT: success for Add validation for DMC firmware header parsing (rev4) Patchwork
  2 siblings, 1 reply; 5+ messages in thread
From: Dibin Moolakadan Subrahmanian @ 2026-09-07 13:50 UTC (permalink / raw)
  To: intel-gfx, intel-xe; +Cc: mitulkumar.ajitkumar.golani, jani.nikula

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: stable@vger.kernel.org
Assisted-by: Claude-Code:Sonnet-5
Signed-off-by: Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com>
---
 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


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v3 2/2] drm/i915/dmc: Harden DMC firmware payload parsing
  2026-09-07 13:50 ` [PATCH v3 2/2] drm/i915/dmc: Harden DMC firmware payload parsing Dibin Moolakadan Subrahmanian
@ 2026-09-07 14:06   ` sashiko-bot
  0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-09-07 14:06 UTC (permalink / raw)
  To: Dibin Moolakadan Subrahmanian; +Cc: intel-xe, intel-gfx

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] Partial initialization of `dmc_info` on payload allocation failure leaves a stale `mmio_count`, leading to unintended hardware MMIO programming for missing firmwares.
--

commit bbb6b21d216798e993d4045cdf8b46c4ba305c9b
Author: Dibin Moolakadan Subrahmanian <dibin.moolakadan.subrahmanian@intel.com>

drm/i915/dmc: Harden DMC firmware payload parsing

This commit validates the DMC firmware size conversion using
check_mul_overflow() to prevent integer overflow. It also rejects zero-length
payloads and zero MMIO counts, and delays setting dmc_fw_size until after the
payload allocation succeeds.

> diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c
> --- a/drivers/gpu/drm/i915/display/intel_dmc.c
> +++ b/drivers/gpu/drm/i915/display/intel_dmc.c

[ ... ]

> @@ -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;

[Severity: High]
This is a pre-existing issue, but partial initialization of dmc_info here
leaves a stale mmio_count on allocation failure.

Since this patch already moves the dmc_fw_size assignment below the kmalloc
check to avoid leaving stale state, should mmio_count and start_mmioaddr be
moved down as well?

If kmalloc() fails, parse_dmc_fw_header() returns 0 but leaves
dmc_info->mmio_count set to a non-zero value. Later in the firmware loading
sequence, intel_dmc_load_program() will proceed to call dmc_load_program()
for the failed secondary DMC, where it calls:

drivers/gpu/drm/i915/display/intel_dmc.c:dmc_load_program() {
    ...
    dmc_load_mmio(display, dmc_id);
    ...
}

Does this cause dmc_load_mmio() to iterate up to the stale mmio_count and
write the partially initialized mmiodata to hardware registers for a
firmware payload that was never loaded?

> +	dmc_info->dmc_fw_size = dmc_header->fw_size;
> +
>  	payload = (u8 *)(dmc_header) + header_len_bytes;
>  	memcpy(dmc_info->payload, payload, payload_size);
>

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260907135048.1403587-4-dibin.moolakadan.subrahmanian@intel.com?part=2

^ permalink raw reply	[flat|nested] 5+ messages in thread

* ✓ i915.CI.BAT: success for Add validation for DMC firmware header parsing (rev4)
  2026-09-07 13:50 [PATCH v3 0/2] Add validation for DMC firmware header parsing Dibin Moolakadan Subrahmanian
  2026-09-07 13:50 ` [PATCH v3 1/2] drm/i915/dmc: Add sanity check for DMC load address Dibin Moolakadan Subrahmanian
  2026-09-07 13:50 ` [PATCH v3 2/2] drm/i915/dmc: Harden DMC firmware payload parsing Dibin Moolakadan Subrahmanian
@ 2026-09-07 16:01 ` Patchwork
  2 siblings, 0 replies; 5+ messages in thread
From: Patchwork @ 2026-09-07 16:01 UTC (permalink / raw)
  To: Dibin Moolakadan Subrahmanian; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 1023 bytes --]

== Series Details ==

Series: Add validation for DMC firmware header parsing (rev4)
URL   : https://patchwork.freedesktop.org/series/170409/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_19096 -> Patchwork_170409v4
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_170409v4/index.html

Participating hosts (40 -> 37)
------------------------------

  Missing    (3): bat-dg2-13 fi-snb-2520m bat-adls-6 


Changes
-------

  No changes found


Build changes
-------------

  * Linux: CI_DRM_19096 -> Patchwork_170409v4

  CI-20190529: 20190529
  CI_DRM_19096: 547f981c369d4b8adf60c5d282b37854f11dab17 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_9084: 9084
  Patchwork_170409v4: 547f981c369d4b8adf60c5d282b37854f11dab17 @ git://anongit.freedesktop.org/gfx-ci/linux

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_170409v4/index.html

[-- Attachment #2: Type: text/html, Size: 1588 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-09-07 16:02 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-07 13:50 [PATCH v3 0/2] Add validation for DMC firmware header parsing Dibin Moolakadan Subrahmanian
2026-09-07 13:50 ` [PATCH v3 1/2] drm/i915/dmc: Add sanity check for DMC load address Dibin Moolakadan Subrahmanian
2026-09-07 13:50 ` [PATCH v3 2/2] drm/i915/dmc: Harden DMC firmware payload parsing Dibin Moolakadan Subrahmanian
2026-09-07 14:06   ` sashiko-bot
2026-09-07 16:01 ` ✓ i915.CI.BAT: success for Add validation for DMC firmware header parsing (rev4) Patchwork

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox