DF-3654 / verdict.json
{ "finding_id": "DF-3654", "status": "inconclusive", "reproduced": 0, "impact": "none", "confidence": "likely", "verdict": "Source-certain locking defect, hardware-gated runtime. handle_hpd_rx_irq() takes aconnector->hpd_lock iff dc_link->type != dc_connection_mst_branch on ENTRY (amdgpu_dm.c:1209-1210) but releases it iff the same condition holds on EXIT (1251-1254), re-reading the field after dc_link_detect() (1232) which can rewrite it in-handler: single->mst_branch at dc_link.c:528 (branch discovered from sink DPCD) and mst_branch->single at dc_link.c:569 (dm_helpers_dp_mst_start_top_mgr failure, sink-controlled sideband). Direction 1 strands hpd_lock permanently: later handle_hpd_irq() work items for the connector block forever (amdgpu_dm.c:1083), dm_suspend/dm_resume hang (864/878), amdgpu_dm_irq_fini flush_work() hangs (amdgpu_dm_irq.c:334) \u2014 persistent DoS. Direction 2 executes mutex_unlock() (= lockmgr LK_RELEASE) on a never-held lock (sys/dev/drm/include/linux/mutex.h:39) \u2014 lock corruption/panic. The pairing matrix was demonstrated on-guest by the harness (run.log); the kernel handler itself cannot run on the virtio-only guest (env.txt: no AMD GPU). likely rather than certain only because the in-handler type-flip hardware sequence (short-pulse HPD-RX that runs detection discovering/losing the branch) is device-timing-dependent \u2014 the DF-3626 sink-controlled-condition class.", "exploit_chain": "Malicious/defective DisplayPort dock or sink (physical or supply-chain): presents MST branch caps so an HPD-RX short pulse causes dc_link_detect() inside handle_hpd_rx_irq() to flip link->type single->mst_branch while hpd_lock is held -> lock stranded -> all later HPD processing for the connector, suspend/resume, and driver teardown hang permanently. Alternate direction: make topology start fail after the link is classified MST to trigger unlock-without-hold -> lockmgr state corruption/panic.", "evidence": "run.log (pairing matrix: STRANDED LOCK and UNLOCK WITHOUT HOLD cells with dc_link.c:528/569 annotations); VERDICT.md (full source trace incl. lock shim mapping); fix.diff (cached lock decision; git apply --check clean); env.txt (guest virtio-only)", "kernel_refs": [ "sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm.c:1209", "sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm.c:1232", "sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm.c:1251", "sys/dev/drm/amd/display/dc/core/dc_link.c:528", "sys/dev/drm/amd/display/dc/core/dc_link.c:569", "sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm.c:1083", "sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c:334" ], "poc_changes": "no seeded PoC for pass-2; harness written fresh \u2014 enumerates the entry x exit decision matrix exactly as the kernel computes the two conditionals", "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": 55, "guest_dirty": 0, "build_cmd": "cc -O2 -Wall -o harness harness.c", "run_cmd": "./harness", "code_hash": "9fa3a99168441f5c0028d09c5bc6b1108d7b41557175e81ff4ea851db1eb7562", "notes": "pass 2 amdgpu_dm.c; sink-driven surface per briefing item (2); guest scratch removed", "recommended_fix": "Cache the lock decision at handler entry (bool hpd_lock_taken = dc_link->type != dc_connection_mst_branch) and gate lock and unlock on the cached value.", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "Hardware-gated: requires an amdgpu-backed DP connector and a sink that flips the link classification inside one HPD-RX handling. fix.diff makes lock/unlock symmetric on a cached decision; git apply --check verified against sys/; not applied (read-only audit target).", "fix_evidence": "fix.diff in this pack" } |