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

dcn10_enable_per_frame_crtc_position_reset dereferences triggered_crtc_reset.event_source without NULL check (dead path; DF-3948 twin)

Summary

The hwss hook passes grouped_pipes[i]->stream->triggered_crtc_reset.event_source->status.primary_otg_inst into enable_crtc_reset with no NULL check β€” dcn10 twin of DF-3948. Dead path in this tree: triggered_crtc_reset.enabled has no producer and enable_timing_multisync filters out every pipe before the hook can run. Upstream removed the deref by v5.4. None today; if the multisync trigger TODO is ever enabled, a stream with .enabled=true and no master NULL-derefs.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3979 Β· 5 files
FileTypeDescriptionSize
README.md β€” 1.5 KB ↓ raw
VERDICT.md β€” 2.1 KB ↓ raw
df3979_event_source.c β€” 1.3 KB view raw
manifest.json β€” 625 B view raw
verdict.json β€” 1.8 KB view raw

DF-3979 β€” dcn10: unchecked event_source deref in per-frame CRTC reset (dead path; DF-3948 twin)

File: sys/dev/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c:1406 Severity: Info (dead path today β€” same classification as DF-3948, the dce110 twin) Hardware: DCN10 (Raven/Raven2) β€” absent from the audit guest; source-level certainty.

dcn10_enable_per_frame_crtc_position_reset() passes grouped_pipes[i]->stream->triggered_crtc_reset.event_source->status.primary_otg_inst straight into tg->funcs->enable_crtc_reset(...). event_source is NULL for a stream whose triggered_crtc_reset.enabled is true but whose master was never assigned. Upstream Linux removed this deref by v5.4 (passes 0).

Why dead in this tree: triggered_crtc_reset.enabled has no producer β€” dm_enable_per_frame_crtc_master_sync() (amdgpu_dm.c:2835-2852) only reads .enabled (the VSDB multisync enable is a TODO) and dc_stream_state is zero-allocated, so enable_timing_multisync() (dc.c:785-807) filters every pipe at dc.c:794-795 and never reaches the hwss hook. set_master_stream() (amdgpu_dm.c:2812-2833) does assign event_source but only runs under the same dead flag.

Fix: mirror upstream v5.4 (pass 0 / drop the deref) or guard if (event_source == NULL) continue;. No runtime PoC is meaningful: dead code plus no DCN hardware in the guest.

Files

  • df3979_event_source.c β€” documentation stub (not a runnable trigger)
  • VERDICT.md, manifest.json, verdict.json
VERDICT.md
↓ download raw

DF-3979 β€” VERDICT

Status: inconclusive (hardware-gated: no DCN10 GPU in the audit guest) β€” and the deref is a dead path in this tree regardless, so no runtime demonstration is possible by construction.

Root cause (source-certain): dcn10_enable_per_frame_crtc_position_reset() at sys/dev/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c:1406 evaluates grouped_pipes[i]->stream->triggered_crtc_reset.event_source->status.primary_otg_inst with no NULL check on event_source. struct dc_crtc_trigger embeds const struct dc_stream_state *event_source; a stream with triggered_crtc_reset.enabled == true created before set_master_stream() runs (or with a NULL master) has event_source == NULL.

Unreachability proof (this tree): 1. The only writer of triggered_crtc_reset.event_source is set_master_stream() (amdgpu_dm.c:2829-2832), called only from dm_enable_per_frame_crtc_master_sync() (amdgpu_dm.c:2835). 2. dc_stream_state is kzalloc'd (dc_stream_create, core/dc_stream.c), so .enabled starts false; a tree-wide grep finds no producer setting triggered_crtc_reset.enabled = true (the enable is a TODO at amdgpu_dm.c:2844-2846). 3. The only caller, enable_timing_multisync() (core/dc.c:785), skips every pipe with !stream->triggered_crtc_reset.enabled (dc.c:794) and only invokes the hwss hook with a non-empty group; with .enabled always false the hook is never called.

Upstream disposition: Linux v5.4's dcn10_enable_per_frame_crtc_position_reset no longer dereferences event_source (passes 0 as the master OTG instance) β€” the fix to mirror.

Recommendation: align with upstream (drop the deref) or add an event_source == NULL guard, matching the DF-3948 fix on the dce110 twin.

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_testable
baseline no→ patch + rebuild →patched clean

Info/dead-path finding; no fix validation applicable (no hardware, path unreachable).

n/a
per-fix-DF-3979

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md: producer grep (no writer of .enabled), dc.c:794 gate, upstream v5.4 comparison.

PoC changes

n/a (documentation stub only)

Verified recommended fix

Match upstream v5.4: stop dereferencing event_source in the dcn10 hook (pass 0), or add an explicit NULL guard.

Verdict

dcn10_enable_per_frame_crtc_position_reset (dcn10_hw_sequencer.c:1406) dereferences triggered_crtc_reset.event_source->status.primary_otg_inst without a NULL check -- the dcn10 twin of DF-3948 (dce110). Dead path in this tree: triggered_crtc_reset.enabled has no producer (amdgpu_dm.c TODO), dc_stream_state is zero-allocated, and enable_timing_multisync (dc.c:794) filters out every pipe before the hwss hook can be reached. Upstream Linux removed the deref by v5.4 (passes 0). No DCN10 GPU on the audit guest and the path is dead by construction, so no runtime demonstration is possible; source certainty only.