DF-3653 / verdict.json
{ "finding_id": "DF-3653", "status": "inconclusive", "reproduced": 0, "impact": "none", "confidence": "certain", "verdict": "Source-certain NULL deref, hardware-gated runtime. amdgpu_dm_atomic_commit_tail() calls update_stream_scaling_settings(..., dm_new_crtc_state->stream) at amdgpu_dm.c:4882 BEFORE the NULL check at 4885; update_stream_scaling_settings() only guards !mode (2473) and mode is &crtc->mode (embedded struct, never NULL), so stream->timing.h_addressable (2479) faults at VA 0x10 on amd64 (sink ptr + h_total + h_border_left). Deterministic trigger by a DRM-master local client in 3 atomic commits: disable CRTC; attach connector with MODE_ID set but ACTIVE=0 (stream is never created because modereset_required() short-circuits on active==0 at 5293-5294, and the BUG_ON at 5344 is skipped by the active term at 5333-5335); then change only underscan properties (CRTC enters the state via drm_atomic_get_connector_state, drm_atomic.c:819-826; needs_modeset false; is_scaling_state_different true) -> commit tail enters the scaling block with stream==NULL -> panic. The userspace model (verbatim struct field order) SIGSEGVs at the identical 0x10 offset on the guest (run.log EXIT=139). Guest is virtio-only with no AMD display device (env.txt), so the kernel path itself cannot execute: inconclusive overall; impact ceiling is local DoS (panic) via DRM_IOCTL_MODE_ATOMIC (DRM_MASTER, drm_ioctl.c:681) \u2014 no disclosure/control primitive (fixed-VA NULL read).", "exploit_chain": "Local user with DRM master (console when no compositor runs, or a malicious compositor): atomic commit 1 disables the CRTC and detaches the connector; commit 2 re-attaches the connector with a mode but ACTIVE=0 leaving dm_crtc_state->stream==NULL while connector->state->crtc points at the enabled-but-inactive CRTC; commit 3 sets underscan=1 + hborder/vborder=1 on the connector only -> amdgpu_dm_atomic_commit_tail enters the scaling block with !needs_modeset -> update_stream_scaling_settings dereferences NULL stream at 0x10 -> kernel page fault/panic. Requires a connected (or forced) display so mode_valid passes in commit 2.", "evidence": "run.log (offsetof=0x10 trace then SIGSEGV EXIT=139); VERDICT.md (full 3-commit source trace with drm_atomic.c/drm_atomic_helper.c line proofs); fix.diff (guard moved before the call; git apply --check clean); env.txt (guest has no AMD GPU: pciconf 0x1002 count 0, /dev/dri absent)", "kernel_refs": [ "sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm.c:4882", "sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm.c:4885", "sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm.c:2479", "sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm.c:5293", "sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm.c:5333", "sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm.c:5344", "sys/dev/drm/drm_atomic.c:819", "sys/dev/drm/drm_ioctl.c:681" ], "poc_changes": "no seeded PoC for pass-2; harness written fresh \u2014 models the commit-tail decision sequence and replicates the verbatim dc_stream_state/dc_crtc_timing field order so the fault address (0x10) equals the kernels", "attempts": 1, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "runtime_sec": 95, "guest_dirty": 0, "build_cmd": "cc -O2 -Wall -o harness harness.c", "run_cmd": "./harness", "code_hash": "a3024949615f1167baf5084462dca6cd20962273c52bb858ba82bbf85ca4dd5c", "notes": "pass 2 amdgpu_dm.c; sibling of the DF-1152 BUG_ON family but a distinct location (commit tail vs atomic check) with a distinct deterministic trigger; guest scratch files removed after run", "recommended_fix": "Move the !dm_new_crtc_state->stream check before the update_stream_scaling_settings() call in amdgpu_dm_atomic_commit_tail().", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "Fix validation requires AMD display hardware (driver cannot attach on the virtio-only guest). fix.diff moves the NULL guard before the call \u2014 with it, commit 3 skips the scaling update exactly as the atomic-check phase (amdgpu_dm.c:5333-5344) already does. git apply --check verified against sys/; not applied (read-only audit target).", "fix_evidence": "fix.diff in this pack; applies cleanly per git apply --check" } |