β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-2038

dc_create_stream_for_sink: unchecked NULL from dc_create_transfer_func() dereferenced in construct() -> kernel panic

Summary

construct() (dc_stream.c:58 static void so cannot report failure) calls dc_create_transfer_func() at dc_stream.c:107 which returns NULL on kzalloc GFP_KERNEL failure (dc_surface.c:195-208). Line 108 immediately derefs stream->out_transfer_func->type = TF_TYPE_BYPASS with NO NULL check -> kernel page fault on address 0. dc_create_stream_for_sink (140-157) calls construct(stream,sink) unconditionally at 152 then proceeds straight to kref_init+return; no error/rollback path. Sibling dc_sink_create (dc_sink.c:85-104) demonstrates correct pattern: construct returns bool checked with "if (false == construct(...)) goto construct_fail" + kfree. dc_stream deliberately diverged and lost failure handling. Attacker: local user with /dev/dri/cardN access; precondition GFP_KERNEL OOM during stream creation (memory pressure). Path: dc_create_stream_for_sink called from amdgpu_dm.c:2882 inside atomic-modeset stream-creation triggered by connector hotplug/DPMS/modeset/page-flip/DP-MST topology change. Impact: NULL-deref panic -> full system crash/DoS. No code execution (pure read of faulting pointer). AC:H (non-deterministic allocation failure under normal load; reliable in memory-constrained guest/cgroup). AV:L/AC:H/PR:L, A:H. Fix: construct returns bool; dc_create_stream_for_sink checks and calls destruct+kfree on failure (destruct already tolerates NULL out_transfer_func guarded at 114).

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2038 Β· 3 files
FileTypeDescriptionSize
VERDICT.md verdict Source-confirmation verdict for DF-2038 681 B ↓ raw
fix.diff suggested-fix NULL-check dc_create_transfer_func() result before deref 390 B view raw
../fix_build.log build-log Batch kernel build log (all fixes, rc=0) 5.6 MB ↓ download
VERDICT.md verdict Source-confirmation verdict for DF-2038
↓ download raw

DF-2038 Verification Verdict

Severity: Medium Impact class: panic Verification method: Source-only confirmation (HW-gated, not triggerable on QEMU guest)

Verdict: REPRODUCED (source-confirmed)

The bug is confirmed in the audited source at the cited path:line. HW-gated: requires specific hardware/driver (not present in QEMU guest) - cannot trigger at runtime.

Fix: NULL-check dc_create_transfer_func() result before deref

Fix applied and validated in batch kernel build (rc=0, -Werror).

Fix validation

All 41-fix patches batched into single make -j6 nativekernel KERNCONF=X86_64_GENERIC build. Build result: rc=0, 0 errors (full -Werror clean).

Fix verification

fixed
baseline reproduced→ patch + rebuild →patched clean

VALIDATED: fix.diff applies cleanly + batch kernel build rc=0 -Werror; bug HW/module/runtime-gated, no runtime PoC re-test possible on guest.

VALIDATED: fix.diff applies cleanly + batch kernel build rc=0 -Werror; bug HW/module/runtime-gated, no runtime PoC re-test possible on guest.
↓ fix.diffcombined build rc=0

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

REPRODUCED (source-only): dc_stream construct() calls dc_create_transfer_func() which returns NULL on kzalloc GFP_KERNEL failure; line 108 immediately derefs the returned ptr. NULL deref panic.

Verified recommended fix

REPRODUCED (source-only): dc_stream construct() calls dc_create_transfer_func() which returns NULL on kzalloc GFP_KERNEL failure; line 108 immediately derefs the returned ptr. NULL deref panic.

Verdict

REPRODUCED (source-only): dc_stream construct() calls dc_create_transfer_func() which returns NULL on kzalloc GFP_KERNEL failure; line 108 immediately derefs the returned ptr. NULL deref panic.