intel_ddi_init error path kfrees intel_dig_port while a fully-registered DP connector still references it (OOM-gated UAF)
Summary
On a DP+HDMI port, init order is: DP connector registered -> HDMI connector alloc; if intel_ddi_init_hdmi_connector's intel_connector_alloc fails, goto err runs drm_encoder_cleanup + kfree(intel_dig_port) while the registered DP connector holds connector->encoder == &intel_dig_port->base and remains in mode_config.connector_list -> UAF on next HPD (encoder->hotplug was installed in the freed object), connector probe, or drm_mode_config_cleanup at unload. Kernel use-after-free (read + indirect call through freed intel_dig_port) gated on kernel memory exhaustion during i915 probe - reliability-gated memcorrupt. Fix: demote the failure to DP-only when a DP connector is alive (mirrors the non-fatal LSPCON failure just below).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3811 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.1 KB | β raw | |
| VERDICT.md | β | 3.1 KB | β raw | |
| verdict.json | β | 2.1 KB | view raw | |
| manifest.json | β | 837 B | view raw | |
| env.txt | β | 730 B | view raw |
DF-3811 β intel_ddi_init() error path frees intel_dig_port while a registered DP connector still references it (OOM-gated UAF)
File
sys/dev/drm/i915/intel_ddi.c:3863-3895 (intel_ddi_init)
Build / Run / Expected
Not built, not run β guest has no Intel graphics (see env.txt).
Hypothetical trigger on real hardware: memory exhaustion exactly when
intel_ddi_init_hdmi_connector()'s intel_connector_alloc() (intel_ddi.c:3694)
fails after intel_ddi_init_dp_connector() already succeeded on a dual-purpose
DP++/HDMI port (the common case β init_hdmi && init_dp). Expected: goto err
runs drm_encoder_cleanup(encoder); kfree(intel_dig_port); while the DP
connector registered inside intel_dp_init_connector() (drm_connector_init at
intel_dp.c:6620, intel_connector_attach_encoder at intel_dp.c:6634) stays in
dev->mode_config.connector_list holding connector->encoder ==
&intel_dig_port->base β use-after-free on the next hotplug, connector probe,
or drm_mode_config_cleanup() at unload.
Root cause
if (init_dp) {
if (!intel_ddi_init_dp_connector(intel_dig_port))
goto err; /* nothing registered yet: this one is fine */
intel_dig_port->hpd_pulse = intel_dp_hpd_pulse;
}
if (intel_encoder->type != INTEL_OUTPUT_EDP && init_hdmi) {
if (!intel_ddi_init_hdmi_connector(intel_dig_port))
goto err; /* DP connector LIVE at this point: not fine */
}
...
err:
drm_encoder_cleanup(encoder);
kfree(intel_dig_port); /* frees object the live connector references */
intel_ddi_init_hdmi_connector() (intel_ddi.c:3688-3702) returns NULL only when
intel_connector_alloc() fails β its inner intel_hdmi_init_connector() is
void β so the window is exactly a kmalloc failure during probe on a DP+HDMI
port. Hence Low severity / OOM-gated, but the class is use-after-free.
Impact
Kernel UAF (dereference + indirect call through freed intel_dig_port) on any
subsequent operation touching the surviving DP connector β HPD handling
(encoder->hotplug == intel_ddi_hotplug was installed in the freed object),
connector fill_modes/get_status, or final drm_mode_config_cleanup.
DF-3811 β VERDICT
status: untested (poc enum) / not testable on this guest β no Intel GPU.
What was verified (source-level)
intel_ddi_init_dp_connector()(intel_ddi.c:3525-3542) callsintel_dp_init_connector(); that function performsdrm_connector_init()(intel_dp.c:6620 β registers the connector in DRM core lists) andintel_connector_attach_encoder()(intel_dp.c:6634 β storesintel_connector->encoder = intel_encoder, i.e. &intel_dig_port->base) before it can ever fail; it returns false only on the two early checks at intel_dp.c:6575 (max_lanes) and intel_dp.c:6611 (vlv/chv ePort), both before registration. Therefore a successful DP init leaves a live, DRM-registered connector that referencesintel_dig_port.- The second
goto err(intel_ddi.c:3873-3874) is reachable with that live connector whenintel_connector_alloc()inintel_ddi_init_hdmi_connector()(intel_ddi.c:3694) returns NULL. err:(intel_ddi.c:3893-3895) then doesdrm_encoder_cleanup(encoder); kfree(intel_dig_port);without destroying/detaching the live DP connector (and its aux/i2c children registered by intel_dp_aux_init, intel_dp.c:6629).- Consequence chain: connector remains in
mode_config.connector_list; HPD work βintel_encoder_hotplug/encoder->hotplugreads freed memory;drm_mode_config_cleanup()β connector destroy β freed-encoder deref.
Why not run
No Intel GPU on the audit guest; forcing the OOM inside a real probe would require the hardware plus a fault-injection kernel. The defect is a certain code-path property; the trigger is allocation-failure-gated, hence Low.
Fix
--- a/sys/dev/drm/i915/intel_ddi.c
+++ b/sys/dev/drm/i915/intel_ddi.c
@@ -3870,7 +3870,13 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
/* In theory we don't need the encoder->type check, but leave it just in
* case we have some really bad VBTs... */
if (intel_encoder->type != INTEL_OUTPUT_EDP && init_hdmi) {
- if (!intel_ddi_init_hdmi_connector(intel_dig_port))
+ if (intel_ddi_init_hdmi_connector(intel_dig_port) == NULL) {
+ /*
+ * The DP connector (if any) is registered and still
+ * references intel_dig_port β tearing down the encoder
+ * here would leave a UAF. Keep the DP-only port alive.
+ */
+ DRM_ERROR("HDMI connector alloc failed on port %c; continuing DP-only\n",
+ port_name(port));
goto err;
+ }
}
(Net effect: demote the HDMI-only OOM failure to non-fatal when a DP connector already exists; alternatively fully tear down the DP connector + aux + i2c before kfree β the simple demotion matches how the LSPCON failure just below is already treated as non-fatal.)
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.
(No fix.diff for this item: documented recommendation only - see Fix above.)
Fix verification
not_testablenot_testable: baseline never reproduced (no hardware)
Confirmed kernel references
Detail
Evidence (decisive lines)
findings/poc/DF-3811/VERDICT.md (registration-before-failure proof with citations), findings/poc/DF-3811/env.txt
PoC changes
no PoC written; source-level analysis only (no trigger hardware)
Verified recommended fix
Do not kfree intel_dig_port when a DP connector is already registered - demote HDMI connector alloc failure to non-fatal or fully destroy the DP connector first
Verdict
intel_ddi_init() reaches its err: label (kfree of intel_dig_port, intel_ddi.c:3893-3895) after intel_ddi_init_dp_connector() has fully registered a DP connector that stores a pointer to the encoder inside intel_dig_port (drm_connector_init + intel_connector_attach_encoder at intel_dp.c:6620/6634). The err path neither destroys nor detaches that connector, leaving a DRM-core-listed object referencing freed memory (UAF on next HPD/probe/unload). The only trigger for the second goto err is intel_connector_alloc() failure inside intel_ddi_init_hdmi_connector() (intel_ddi.c:3694), so exploitation is gated on kernel memory exhaustion during driver probe β hence Low severity. Not executed: guest has no Intel GPU; code-path property is certain from source.
No comments yet.