DF-5079 / verdict.json
{ "finding_id": "DF-5079", "status": "reproduced", "reproduced": true, "impact": "panic", "confidence": "certain", "verdict": "Reproduced at logic level with a verbatim userland replica of the dce120 vupdate/vblank entry macros + the dce120-local vblank_irq_info_funcs {.set=dce110_vblank_set} (irq_service_dce120.c:82-85,138-153), dce110_vblank_set itself (irq_service_dce110.c:195-219), to_dal_irq_source_dce110, and the set dispatch (irq_service.c:77-124), run on the audit guest against a 0x5a-poisoned 8MiB current_state with valid timing generators in pipes 0..5. The dce120 vupdate entries carry src_id=0/ext_id=0 (vupdate_int_entry initializes no .src_id, unlike the vblank entries consecutive 19..24), so dce110_vblank_sets re-derivation to_dal_irq_source_dce110(0,0) returns DC_IRQ_SOURCE_INVALID and uint8_t pipe_offset = dal_irq_src - IRQ_TYPE_VBLANK underflows to 178; core_dc->current_state->res_ctx.pipe_ctx[178] reads the poisoned mapping and the very next tg->funcs->arm_vert_intr(tg,2) faults \u2014 SIGBUS exit 138, deterministic x2. VBLANK1..6 controls arm pipes 0..5 through the REAL conversion path, proving the in-tree-reachable vblank path healthy \u2014 this is the DF-4933 (dce110) / DF-5055 (dce80) twin wired independently by the DCE120 tables own macros. The replica also prints the double-baked note: even a correctly remapped VUPDATE source underflows ((uint8_t)(72-78)=250), since the subtraction base is IRQ_TYPE_VBLANK not IRQ_TYPE_VUPDATE (true V_UPDATE src ids are the non-consecutive 7,9,11,13,15,17 per ivsrcid_vislands30.h:30-61). Latent like the family: no in-tree caller ever .sets a VUPDATE source (suspend/resume HPD/HPDRX-only per amdgpu_dm_irq.c:353/380/406,625-645; vblank enable = IRQ_TYPE_VBLANK+otg_inst per amdgpu_dm.c:3014; pflip = IRQ_TYPE_PFLIP; the IH converter returns VUPDATE only for src_ids 7,9..17 which amdgpu_dm never registers), the service exists only on DCE12 hardware (dce120_resource.c:1011), and the guest has no AMD GPU. Ceiling if a future caller appears: far-OOB read feeding a wild indirect call \u2014 a groomed heap around the dc_state allocation could in principle aim tg (not demonstrated; honest ceiling is a kernel panic). FIX VALIDATED: fix.diff (dce120 macro gains .src_id = VISLANDS30_IV_SRCID_D1_V_UPDATE_INT + 2*reg_num = 7,9,..,17; plus the vblank_pipe_offset() table-index helper in dce110_vblank_set \u2014 byte-identical to DF-4933/DF-5055s fix shape, the shared-function owner) applied to guest /usr/src together with DF-5078s (hunks at dce110:192/:226 and dce120:140); full amdgpu.ko rebuild under -Werror rc=0, zero errors, zero warnings, irq_service_dce110.o recompiled and linked (amdgpu_module_build.log:572); replica fixed mode arms the correct pipe 0..5 for all 12 VUPDATE/VBLANK sources, exit 0 vs baseline 138; sources reverted md5-verified pristine, make clean, guest returned to clean snapshot.", "exploit_chain": "", "evidence": "run.log + run.2.log (deterministic x2: vupdate1 src_id=0/ext_id=0 vs vblank1 19; double-baked 250; VBLANK1..6 controls arm pipes 0..5; set(VUPDATE1) -> pipe_ctx[178] -> SIGBUS exit=138; fixed exit=0); dmesg.txt (kernel-observed signal-10 exits); dce120_vupd.c header (path:line map); amdgpu_module_build.log (rc=0, 0/0 under -Werror, irq_service_dce110.o at :571-572)", "kernel_refs": [ "sys/dev/drm/amd/display/dc/irq/dce120/irq_service_dce120.c:138", "sys/dev/drm/amd/display/dc/irq/dce120/irq_service_dce120.c:144", "sys/dev/drm/amd/display/dc/irq/dce120/irq_service_dce120.c:82", "sys/dev/drm/amd/display/dc/irq/dce110/irq_service_dce110.c:201", "sys/dev/drm/amd/display/dc/irq/dce110/irq_service_dce110.c:205", "sys/dev/drm/amd/display/dc/irq/dce110/irq_service_dce110.c:208", "sys/dev/drm/amd/display/dc/irq/dce110/irq_service_dce110.c:211", "sys/dev/drm/amd/display/dc/irq_types.h:153", "sys/dev/drm/amd/include/ivsrcid/ivsrcid_vislands30.h:30", "sys/dev/drm/amd/display/dc/inc/core_types.h:240" ], "poc_changes": "Self-authored by adapting DF-5055s dce80 harness to the dce120 macros: swapped in the dce120 vupdate/vblank entry forms (SRI/IRQ_REG_ENTRY with per-instance stub mask defines), the dce120 funcs/table names, and added the double-baked underflow print ((uint8_t)(VUPDATE1-IRQ_TYPE_VBLANK)=250) plus a fixed-mode loop proving all six VUPDATE sources arm pipes 0..5.", "attempts": 2, "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": 600, "guest_dirty": 0, "build_cmd": "sh /root/df5079/build.sh # cc -O2 -Wall -std=gnu11 [-DFIX_DF5079] -o dce120_vupd_{base,fixed} (rc=0)", "run_cmd": "sh /root/df5079/run.sh # baseline: exit=138 x2; fixed: exit=0 x2", "code_hash": "44d0edf9418f9fa0dc70e9d487a3548894f15adf2220468d1a4378543f940724", "notes": "The dce110 hunk of fix.diff is byte-identical to DF-4933/DF-5055s (the shared-function owner); the dce120 hunk is this findings own (correct odd-spaced V_UPDATE src ids). Fix validation shared one amdgpu.ko rebuild with DF-5078. to_dal conversion (borrowed from dce110) verified complete for every source the DCE12 IH can deliver \u2014 no in-range gap. Guest reset to clean snapshot after the run set (guest_dirty=0).", "recommended_fix": "Derive the pipe from the table INDEX in dce110_vblank_set (vblank_pipe_offset helper, provably 0..5 for both ranges \u2014 DF-4933/DF-5055s shape) and give the dce120 vupdate entries their true src ids (.src_id = VISLANDS30_IV_SRCID_D1_V_UPDATE_INT + 2*reg_num) \u2014 fix.diff carries both hunks.", "fix_status": "fixed", "fix_baseline_reproduced": true, "fix_patched_reproduced": true, "fix_verdict": "fix.diff applied to guest /usr/src together with DF-5078s (hunks at dce110:192/:226, dce120:140); full make -j6 amdgpu.ko rebuild rc=0 with 0 errors/0 warnings under -Werror (amdgpu_module_build.log; irq_service_dce110.c compiled at :571-572); replica fixed mode (identical shape) arms the correct pipe for all 12 VUPDATE/VBLANK sources, exit 0 where baseline exits 138; sources reverted md5-verified pristine (35607b1a.../51bd6ea8...), make clean.", "fix_evidence": "fix_build.log (=amdgpu_module_build.log, rc=0, zero diagnostics); fix_run.log (fixed mode: all 12 sources arm pipes 0..5, exit 0); run.log (baseline exit=138)", "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0 Thu Jul 2 06:02:54 UTC 2026 (amdgpu.ko module rebuilt with fix; not booted \u2014 no AMD GPU on guest)" } |