* [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