vlv_dsi_init dereferences vbt.dsi.config without a NULL/dangling guard β boot-time NULL-page panic or UAF read of freed config
Summary
vlv_dsi_init decides DSI presence from the VBT child-device list but then dereferences dev_priv->vbt.dsi.config with no guard. dsi.config is only set when the separate BDB_MIPI_CONFIG section exists and both kmemdups in parse_mipi_config succeed. Missing section or config-kmemdup OOM => NULL-page deref panic at i915 attach; pps-kmemdup OOM => the producer kfrees config WITHOUT NULLing it => vlv_dsi_init reads freed memory and intel_dsi_vbt_init then parses the entire freed struct. Firmware/OOM-gated. Consumer-guard + producer-NULL fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4205 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.9 KB | β raw | |
| VERDICT.md | β | 2.8 KB | β raw | |
| verdict.json | β | 2.8 KB | view raw | |
| fix.diff | β | 918 B | view raw | |
| manifest.json | β | 962 B | view raw |
DF-4205 β vlv_dsi_init dereferences vbt.dsi.config without NULL/dangling guard
File: sys/dev/drm/i915/vlv_dsi.c (pass 2)
Severity: Low | Confidence: certain | CWE-476 (NULL pointer dereference) / CWE-457 (use of uninitialized/freed pointer variant)
Build / Run
No build or run: Phase V skipped per contract (Low severity, firmware-gated
trigger). The audit QEMU guest has no Intel GPU, so i915 never attaches and
vlv_dsi_init is not reachable there; the trigger additionally requires a
VBT whose child-device list declares a MIPI output while the
BDB_MIPI_CONFIG block is absent (or an OOM at a specific kmemdup).
Static repro of the path is fully cited below β the defect is provable from source alone.
Expected behavior if triggered (on real VLV/CHV/BXT hardware)
- Missing
BDB_MIPI_CONFIG+ MIPI child device present: kernel NULL-page deref panic at driver attach (config->dual_link, vlv_dsi.c:1797). - OOM in the
ppskmemdup afterconfigkmemdup succeeded: 1-byte UAF read at vlv_dsi.c:1797, then full parse of freed memory inintel_dsi_vbt_init(intel_dsi_vbt.c:523-544) and->pwm_blcread at vlv_dsi.c:1826.
The path (path:line)
vlv_dsi_init()vlv_dsi.c:1747 βintel_bios_is_dsi_present(dev_priv, &port)returns true based on the child device list (intel_bios.c:2034-2047: any child withDEVICE_TYPE_MIPI_OUTPUTanddvo_portin {DVO_PORT_MIPIA, DVO_PORT_MIPIC}).dev_priv->vbt.dsi.configis populated by a different BDB section:parse_mipi_config()intel_bios.c:826-830 β iffind_section(bdb, BDB_MIPI_CONFIG)fails it returns withdsi.config == NULL.- intel_bios.c:843-851 β
dsi.config = kmemdup(...); onppskmemdup failure (line 848-851) it doeskfree(dev_priv->vbt.dsi.config)without setting it to NULL β dangling. - Back in vlv_dsi_init: vlv_dsi.c:1797
dev_priv->vbt.dsi.config->dual_linkand vlv_dsi.c:1826dev_priv->vbt.dsi.config->pwm_blcβ dereferenced with no guard.
Nothing between intel_bios_init and vlv_dsi_init re-checks dsi.config or
dsi.panel_id (which stays MIPI_DSI_UNDEFINED_PANEL_ID when the section is
missing β intel_bios.c:816,855).
Distinct from known findings
- DF-1390: OOB indexing inside
parse_mipi_config(config[panel_type]). - DF-1773: NULL-deref of
vbt.lfp_lvds_vbt_modeinintel_dsi_vbt_init(different pointer, later in the call chain β it never runs because vlv_dsi.c:1797 faults first). - DF-4122: block-size floors in other parse_* consumers.
Fix
Guard at the consumer (this file) + NULL the dangling pointer at the
producer β see fix.diff.
Threat model / impact ceiling
Attacker needs to control the Intel VBT (BIOS/OpROM flash = root) or hit a narrow OOM. Impact: kernel panic at driver attach (local DoS of the boot / driver load), not arbitrary code execution. Rooted-firmware supply chain or broken BIOS is the realistic scenario.
DF-4205 VERDICT
Status: untested (Phase V skipped β Low severity, firmware/OOM-gated, no Intel GPU on the audit guest). Bug existence: certain, proven from source.
Root cause
vlv_dsi_init() decides DSI is present from the VBT child device list
(intel_bios_is_dsi_present, intel_bios.c:2034-2047), but then dereferences
dev_priv->vbt.dsi.config (vlv_dsi.c:1797 ->dual_link, :1826 ->pwm_blc)
which is only populated when a different BDB section (BDB_MIPI_CONFIG)
exists AND both kmemdups succeed (intel_bios.c:826-856). The two presence
signals are decoupled; there is no guard at the consumer.
Three concrete failure inputs:
- NULL deref (panic) β VBT has a MIPI child device but no
BDB_MIPI_CONFIGsection:find_section()returns NULL (intel_bios.c:826-830),dsi.configstays NULL,vlv_dsi_initruns to :1797 and faults on the NULL page. Kernel panic at i915 attach. - NULL deref (OOM) β
kmemdup(config)fails (intel_bios.c:843-845): config stays NULL, same fault at :1797. - UAF read β
kmemdup(pps)fails after config succeeded (intel_bios.c:847-851):kfree(dsi.config)leaves the pointer dangling; vlv_dsi.c:1797 readsdual_linkfrom freed memory (1 byte), thenintel_dsi_vbt_init()parses the entire freedstruct mipi_config(intel_dsi_vbt.c:506,523-544) and vlv_dsi.c:1826 readspwm_blc.
Why not verified on the guest
- The audit QEMU guest exposes no Intel GPU; i915 does not attach, so
vlv_dsi_initis unreachable by construction (not_testable conditions). - Even on hardware, the trigger is firmware content (VBT) or a specific OOM, neither of which an unprivileged guest user controls.
- Severity Low β contract exempts from Phase V.
Impact ceiling
Boot/attach-time kernel panic (DoS) in case 1-2; a UAF read of a 484-byte driver-allocated struct in case 3 (no attacker-controlled content is written through it before free β values are copied into intel_dsi fields and programmed to display registers; worst case is garbage register programming after the freed block is reallocated, still no write primitive from userland). No privilege escalation path: the trigger is not user-reachable.
Fix
fix.diff: (a) bail to the (correct, pre-connector) err label when
vbt.dsi.config is NULL in vlv_dsi_init; (b) NULL the pointer after the
pps-failure kfree in intel_bios.c so no dangling pointer survives. Both
hunks are required; neither alone closes case 3.
Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
Fix verification
not_testableNo kernel-build fix validation performed: Low-severity firmware/OOM-gated finding, guest lacks Intel GPU; the two-hunk guard in fix.diff is trivially auditable by inspection.
fix.diff (consumer guard + producer NULL-out); not built or applied to sys/.
Confirmed kernel references
Detail
Evidence (decisive lines)
README.md and VERDICT.md in this pack; decisive lines: vlv_dsi.c:1747 (presence check), vlv_dsi.c:1797+1826 (unguarded deref), intel_bios.c:826-830 (config left NULL), intel_bios.c:848-851 (kfree without NULL), intel_bios.c:2034-2047 (decoupled presence signal), intel_dsi_vbt.c:506+523-544 (later full parse of the same pointer).
PoC changes
No PoC authored: trigger requires a VBT with MIPI child device but no BDB_MIPI_CONFIG block (or a forced kmemdup failure) on real hardware; the audit guest has no Intel GPU. Static proof of path only.
Verified recommended fix
Bail to the pre-connector err label when vbt.dsi.config is NULL in vlv_dsi_init, and NULL the pointer after the pps-failure kfree in parse_mipi_config (fix.diff).
Verdict
Bug existence certain from source trace: vlv_dsi_init dereferences vbt.dsi.config (vlv_dsi.c:1797 ->dual_link, :1826 ->pwm_blc) with no NULL guard, while the pointer is only populated when BDB_MIPI_CONFIG exists and both kmemdups in parse_mipi_config succeed (intel_bios.c:826-856); presence is decided by the separate child-device list (intel_bios.c:2034-2047). Missing section or config-kmemdup OOM => NULL-page panic at attach; pps-kmemdup OOM => dangling config (kfree without NULL, intel_bios.c:848-851) => UAF read of freed struct. Not verified on the guest: no Intel GPU on the audit VM and the trigger is VBT-firmware/OOM-gated, so Phase V is skipped per contract (Low severity). Impact ceiling is a boot/attach panic or a bounded UAF read of driver memory; no userland-reachable write primitive.
No comments yet.