DF-3885 / verdict.json
{ "finding_id": "DF-3885", "status": "inconclusive", "reproduced": 0, "impact": "dos", "confidence": "likely", "verdict": "Hardware-gated DoS: drm_pick_crtcs (drm_fb_helper.c:2422-2495) is an exhaustive recursive search with one unconditional plus one-per-CRTC recursion per connector -- (crtcs+1)^connectors calls when all connectors have modes -- with no budget or depth cap, executed under fb_helper->lock from drm_setup_crtcs (:2602, hotplug/initial-config). connector_count grows unbounded via __drm_fb_helper_add_one_connector (:140-175 krealloc) fed by MST port enumeration (intel_dp_mst.c:497 etc.), and the malicious hub also supplies the modes. A 20-connector topology on a 4-pipe i915 is ~9.5e13 calls: the kms worker pins a CPU for days while lastclose/set_par/blank/ioctl block on the same lock. Guest model verified the x5-per-connector curve (305M calls = 748ms at 12 connectors, run.log; the 15-connector run outran a 120s timeout in optimized C). Kernel path not exercisable on this guest (no GPU, /dev/dri absent, env.txt) -- hence inconclusive rather than reproduced.", "exploit_chain": "malicious hub enumerates 20+ fake connectors each with fabricated EDID modes -> any HPD cycle -> drm_fb_helper_hotplug_event -> drm_setup_crtcs holds fb_helper->lock across a days-long drm_pick_crtcs search -> all fbdev entry points (lastclose, set_par, blank, ioctl) block -> console/DRM wedge (system DoS).", "evidence": "run.log (measured growth 488281 -> 305175781 calls for 8 -> 12 connectors), build.log (15-connector run outrunning the 120s ssh timeout), VERDICT.md (recurrence derivation + killed adjacent candidates), fix.diff validated clean on pristine tree", "kernel_refs": ["sys/dev/drm/drm_fb_helper.c:2440", "sys/dev/drm/drm_fb_helper.c:2483", "sys/dev/drm/drm_fb_helper.c:2602", "sys/dev/drm/drm_fb_helper.c:2855", "sys/dev/drm/i915/intel_dp_mst.c:497"], "poc_changes": "no seed; complexity model authored from scratch (capped at 12 connectors after the 15-connector run outran the ssh timeout)", "attempts": 2, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 x86_64", "runtime_sec": 90, "guest_dirty": 0, "build_cmd": "cc -O2 -Wall -o pick_crtcs_model pick_crtcs_model.c", "run_cmd": "./pick_crtcs_model", "code_hash": "c1786d0fdf78763750ca1066744529846a004fbd4e5b3d76570b671af7025ea9", "notes": "Adjacent candidates killed and recorded in VERDICT.md: per-CRTC connectors[4] overflow unreachable (multi-CRTC clone skip + i915 initial_config clone bail), BIT_ULL(count) wrap is logic-only, deferred-io/pan/setcmap/check_var/fb_{read,write} are #if 0 in this port. /dev/fb0 does not exist on this guest, so the fbdev 0666 question is moot here.", "recommended_fix": "Thread a 2^20-call budget through drm_pick_crtcs and keep the best-so-far assignment when it is exhausted", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff (budget-threaded recursion) applies cleanly to the pristine sys/dev/drm/drm_fb_helper.c via patch --dry-run; kernel-side validation impossible on this guest (no GPU), so fix_status=not_testable.", "fix_evidence": "findings/poc/DF-3885/fix.diff" } |