Hello,

Proposed-fix limitation: the patch below does not validate the full
VBT table extent against the section size. The malformed/short-table
out-of-bounds case described below remains unresolved by these
existence and minimum-count checks. This is an incomplete proposal for
maintainer review; a complete fix still needs section-extent bounds
validation.

parse_vswing_preemph_override() stores the raw pointer and count fields
from VBT block 57 without validating that the block actually contains
the announced table, and allocate_vswing_preemph_override() allocates
the consumer structures whenever a child device sets use_vbt_vswing -
even when the block is absent entirely. validate_vspeo() only checks
that devdata->vspeo is non-NULL and that the port has DP.

Two failure modes follow at DDI buffer-translation time:
 - block absent: tables == NULL, num_columns == 0, so the consumer
   dereferences tables[0] (NULL).
 - block short or malformed: the table walk reads up to
   (5+1)*num_rows*num_columns u32s from a block whose enforced minimum
   size is 2 bytes - with num_columns = 255 that is ~98 KB past a small
   heap allocation, and the values are programmed into PHY registers.

The patch gates the consumer on the table existing with sane counts.
A complete fix should also validate the table extent against the
section size, which is not currently plumbed through; happy to rework
if there is a preferred way to carry the section size.

Affected version/commit: mainline fa4ad798f6f681031775266044ba1b0cf3c670bd 
(v7.4-rc1, 2026-11-07), drivers/gpu/drm/i915/display/intel_bios.c:2216-2234 
(parse), 2654-2676 (allocate), 3874-3923 (validate/consume).
Introduced in the v7.4 merge window.

This was found during an assisted (AI-supported) static source review of
mainline fa4ad798f6f681031775266044ba1b0cf3c670bd (v7.4-rc1, 2026-11-07); every 
code path cited below was re-verified by the
reporter against that tree. The patch below has NOT been compiled and has
NOT been runtime tested, and no reproducer was produced - the triggering
conditions are described above instead. Please treat this as a report for
verification rather than a battle-tested fix.

Reported-by: Noah Weinberger <[email protected]>
---
diff --git a/drivers/gpu/drm/i915/display/intel_bios.c 
b/drivers/gpu/drm/i915/display/intel_bios.c
index 7b6a6f8..d99a675 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -2657,7 +2657,8 @@ static void allocate_vswing_preemph_override(struct 
intel_bios_encoder_data *dev
        union intel_ddi_buf_trans_entry *entries;
        struct intel_ddi_buf_trans *vspeo;
 
-       if (!intel_bios_encoder_requests_vspeo(devdata))
+       if (!intel_bios_encoder_requests_vspeo(devdata) ||
+           !devdata->display->vbt.vspeo.tables)
                return;
 
        vspeo = kzalloc_obj(*vspeo);
@@ -3876,6 +3877,8 @@ validate_vspeo(const struct intel_bios_encoder_data 
*devdata, bool has_dp)
 {
        struct intel_ddi_buf_trans *vspeo;
 
+       struct intel_display *display = devdata->display;
+
        vspeo = devdata->vspeo;
        if (!vspeo)
                return false;
@@ -3883,5 +3886,10 @@ validate_vspeo(const struct intel_bios_encoder_data 
*devdata, bool has_dp)
        if (!has_dp)
                return false;
 
+       if (!display->vbt.vspeo.tables ||
+           display->vbt.vspeo.num_columns < 3 ||
+           display->vbt.vspeo.num_tables < 6)
+               return false;
+
        return true;
 }

Reply via email to