Unchecked kzalloc failure in i915 MST fake-encoder init leads to NULL-deref panic on hub plug-in
| Field | Value |
|---|---|
| ID | DF-1856 |
| Status | new |
| Severity | Low |
| CVSS 3.1 | CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:H |
| CWE | CWE-690 Unchecked Return Value to NULL Pointer Dereference |
| File | sys/dev/drm/i915/intel_dp_mst.c |
| Lines | 541, 580-581, 595 |
| Area | dev/drm/i915 (MST encoder init) |
| Confidence | likely |
| Discovered | 2026-07-20 |
| Reported | pending |
| Known CVE | none |
| CVE match | dfly_specific |
Summary
intel_dp_create_fake_mst_encoder returns NULL on kzalloc failure (line 543),
but intel_dp_create_fake_mst_encoders stores that NULL into
intel_dp->mst_encoders[pipe] (line 580) and unconditionally returns true
(line 581). intel_dp_mst_encoder_init ignores the return value (line 595) and
proceeds to enable MST. Any later dereference of
intel_dp->mst_encoders[pipe]->base.base in intel_mst_atomic_best_encoder
(line 407) or intel_dp_add_mst_connector (line 471) then NULL-dereferences,
panicking the kernel.
Root cause
intel_dp_create_fake_mst_encoder (intel_dp_mst.c:534-570):
intel_mst = kzalloc(sizeof(*intel_mst), GFP_KERNEL);
if (!intel_mst)
return NULL; /* line 543-544 */
The caller intel_dp_create_fake_mst_encoders (lines 572-582) does NOT check
the per-pipe return:
for_each_pipe(dev_priv, pipe)
intel_dp->mst_encoders[pipe] = intel_dp_create_fake_mst_encoder(intel_dig_port, pipe);
return true; /* line 580-581 */
The next-level caller intel_dp_mst_encoder_init (lines 584-603) does:
intel_dp_create_fake_mst_encoders(intel_dig_port); /* return discarded, line 595 */
and unconditionally proceeds to drm_dp_mst_topology_mgr_init, marking MST as
enabled. When a sink/hub is later attached, intel_dp_add_mst_connector at line
469-476 computes &intel_dp->mst_encoders[pipe]->base.base which is
&((struct intel_dp_mst_encoder *)NULL)->base.base β a small constant address.
The subsequent drm_connector_attach_encoder dereference faults.
Likewise intel_mst_atomic_best_encoder (lines 400-408) dereferences
intel_dp->mst_encoders[crtc->pipe]->base.base (line 407) on every atomic
modeset request involving the MST connector.
Threat model & preconditions
- Attacker position: local user who can drive the system into memory pressure during the i915 driver probe / MST initialization window, then trigger a DisplayPort MST hub plug-in event (or trigger one programmatically via DRM modeset ioctls).
- Privileges gained or impact: local denial of service (kernel panic). No privilege escalation, no info leak β availability impact only.
- Required config or capabilities: Intel i915 hardware with MST support compiled in (default). Memory pressure precondition (fork-bomb, hugepage exhaustion, large shm allocations) during driver load.
- Reachability: OOM during probe leaves NULL encoder slots; MST hub plug-in or atomic modeset on the MST connector dereferences them.
Proof of concept
/* mem_pressure.c β drive system into OOM during i915 probe */
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
int main(void){
void *p;
while ((p = mmap(NULL, 1UL<<20, PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, -1, 0)) != MAP_FAILED) {
memset(p, 0x55, 1UL<<20);
}
pause(); /* hold the pressure while i915 probe runs */
return 0;
}
Build & run
cc -O2 mem_pressure.c -o mem_pressure # Run mem_pressure in background, then trigger i915 probe (boot, kldload, # or hot-add). Plug in a DisplayPort MST hub.
Expected output
Fatal trap 12: page fault while in kernel mode faulting address near offsetof(struct intel_dp_mst_encoder, base.base) β 0 intel_dp_add_mst_connector+0x.. at 0x..
Impact
Low-severity (narrow trigger) local DoS. Requires OOM during probe + MST hub plug-in. No escalation primitive.
Recommended fix
Make intel_dp_create_fake_mst_encoders propagate allocation failure and have
intel_dp_mst_encoder_init bail out.
--- a/sys/dev/drm/i915/intel_dp_mst.c
+++ b/sys/dev/drm/i915/intel_dp_mst.c
@@ -572,11 +572,18 @@ static struct intel_dp_mst_encoder *
static bool
intel_dp_create_fake_mst_encoders(struct intel_digital_port *intel_dig_port)
{
struct intel_dp *intel_dp = &intel_dig_port->dp;
struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
enum i915_pipe pipe;
+ int i;
- for_each_pipe(dev_priv, pipe)
- intel_dp->mst_encoders[pipe] = intel_dp_create_fake_mst_encoder(intel_dig_port, pipe);
- return true;
+ for_each_pipe(dev_priv, pipe) {
+ intel_dp->mst_encoders[pipe] = intel_dp_create_fake_mst_encoder(intel_dig_port, pipe);
+ if (!intel_dp->mst_encoders[pipe]) {
+ for (i = 0; i < pipe; i++)
+ intel_dp_mst_encoder_destroy(&intel_dp->mst_encoders[i]->base);
+ return false;
+ }
+ }
+ return true;
}
@@ -590,8 +597,12 @@ int
struct intel_dp *intel_dp = &intel_dig_port->dp;
struct drm_device *dev = intel_dig_port->base.base.dev;
int ret;
intel_dp->can_mst = true;
intel_dp->mst_mgr.cbs = &mst_cbs;
- /* create encoders */
- intel_dp_create_fake_mst_encoders(intel_dig_port);
+ /* create encoders */
+ if (!intel_dp_create_fake_mst_encoders(intel_dig_port)) {
+ intel_dp->can_mst = false;
+ return -ENOMEM;
+ }
ret = drm_dp_mst_topology_mgr_init(&intel_dp->mst_mgr, dev,
&intel_dp->aux, 16, 3, conn_base_id);
Timeline
- 2026-07-20 Discovered during automated audit.
- 2026-07-20 Reported to DragonFlyBSD security contact (pending).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1856 Β· 4 files| File | Type | Description | Size | |
|---|---|---|---|---|
| fix.diff | suggested-fix | git-apply-able fix for the cited bug | 515 B | view raw |
| VERDICT.md | verdict | source-confirmation analysis | 1.0 KB | β raw |
| build.sh | build-script | N/A (source-only) | 65 B | view raw |
| run.sh | run-script | N/A (source-only) | 89 B | view raw |
DF-1856 VERDICT
Verdict: REPRODUCED (source-confirmed)
Impact: Low (driver-level NULL deref / OOB / leak / DoS β hardware-gated)
Mechanism: intel_dp_create_fake_mst_encoder L541 kzalloc(sizeof(*intel_mst),GFP_KERNEL) if(!intel_mst) return NULL L543-544. Caller intel_dp_create_fake_mst_encoders L579-581 for_each_pipe intel_dp->mst_encoders
Citation: sys/dev/drm/i915/intel_dp_mst.c:541-595
Fix: Applied fix.diff β compiles in batch kernel build (rc=0, -Werror).
Verification method: Source-only line-by-line trace of cited path:line. Low-severity driver bug; PoC trigger requires specific hardware or root context. Confirmed the cited vulnerable pattern exists in source.
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
fixedfix.diff compiled in batch kernel build rc=0 -Werror
fix.diff compiled in batch kernel build rc=0 -Werror
Confirmed kernel references
β
Detail
Exploit chain
none (Low severity)
Evidence (decisive lines)
Source-confirmed: unchecked kzalloc failure in i915 MST fake-encoder init (intel_dp_mst.c:541-595)
Verified recommended fix
Source-confirmed: unchecked kzalloc failure in i915 MST fake-encoder init (intel_dp_mst.c:541-595)
Verdict
Source-confirmed: unchecked kzalloc failure in i915 MST fake-encoder init (intel_dp_mst.c:541-595)
No comments yet.