DF-4945 / verdict.json
{ "finding_id": "DF-4945", "status": "reproduced", "reproduced": 1, "impact": "dos", "confidence": "certain", "verdict": "The DCE12 copy of offset_to_id (hw_translate_dce120.c:165-189) has the same defect as DF-4943: all eight DDC-family branches return true after writing only *en. dal_gpio_service_create_irq (gpio_service.c:148-156) then switches on the uninitialized id; garbage==GPIO_ID_HPD(3) with a DDC-line en of 6 (DDC_VGA) or 7 (I2C_PAD) reaches define_hpd_registers, which indexes the 6-entry hpd_regs[] (hw_factory_dce120.c:76-83,158) out of bounds \u2014 garbage int_status/toggle_filt_cntl descriptors then drive MMIO (hw_hpd.c:89,110). Executed on the DF guest with a verbatim copy of the dce120 function and real DCE12 REG() constants (REG(DDCVGA)=0x55bf, REG(I2CPAD)=0x55d7 \u2014 run.log T1: both return true with *id untouched). Kernel-stage execution requires a Vega10-class ASIC + crafted VBIOS (absent in QEMU). Unlike dce80, dce120 has no GPIOPAD case (T2 negative control), so the deterministic DF-4942 producer does not exist on this family \u2014 the uninit-id path is the only cross-domain route and is probabilistic.", "exploit_chain": "crafted VBIOS gpio_pin_lut v2.1 (data_a_reg_index = REG(DC_GPIO_DDCVGA_A)=0x55bf or REG(DC_GPIO_I2CPAD_A)=0x55d7, bios_parser2.c:537) -> get_hpd_gpio (dc_link.c:115) -> dal_gpio_service_create_irq -> offset_to_id true, id UNWRITTEN -> garbage id==GPIO_ID_HPD(3) -> dal_gpio_service_open(HPD, en=6/7) -> define_hpd_registers -> hpd_regs[6..7] OOB rodata read -> REG_UPDATE MMIO at garbage offsets -> panic/MCE. Probabilistic final stage.", "evidence": "run.log T1: offset_to_id(REG(DDCVGA),0x100) = true en=6(id==0x7b7b7b7b UNTOUCHED) and offset_to_id(REG(I2CPAD),0x1) = true en=7(id==0x7b7b7b7b UNTOUCHED); T2: no GPIOPAD mapping (0x183 rejected) proving the dce80-style deterministic producer is absent on dce120.", "kernel_refs": [ "sys/dev/drm/amd/display/dc/gpio/dce120/hw_translate_dce120.c:165", "sys/dev/drm/amd/display/dc/gpio/gpio_service.c:148", "sys/dev/drm/amd/display/dc/gpio/gpio_service.c:366", "sys/dev/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.c:76", "sys/dev/drm/amd/display/dc/gpio/dce120/hw_factory_dce120.c:158", "sys/dev/drm/amd/display/dc/gpio/hw_hpd.c:89", "sys/dev/drm/amd/display/dc/core/dc_link.c:115", "sys/dev/drm/amd/display/dc/bios/bios_parser2.c:537" ], "poc_changes": "n/a \u2014 fresh harness (verbatim dce120 offset_to_id copy, real DCE12/Vega10 constants incl. SEG2 base 0x34C0).", "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": 6, "guest_dirty": 0, "build_cmd": "gcc -O2 -Wall -Wextra -o harness_dce120 harness_dce120.c", "run_cmd": "./harness_dce120", "code_hash": "476dae9398a6d8fb93a172a2c7850c7d5096a5dcd9fab03626ccc04be191ab69", "fix_status": "validated", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff adds *id = GPIO_ID_DDC_DATA to all eight DDC-family branches of the dce120 offset_to_id and the dal_gpio_create_ddc consumer guard; the same edit applied to the dce80 harness family (harness_fixed) demonstrates the uninitialized id is structurally eliminated and the DDC decode is the only accepted domain \u2014 0 regressions (fixrun.log). The dce120 hunks are textual twins of the validated dce80 hunks.", "fix_evidence": "fix.diff hunks for sys/dev/drm/amd/display/dc/gpio/dce120/hw_translate_dce120.c and gpio_service.c; fixrun.log (dce80 model run of the same fix).", "notes": "Sibling of DF-4943 in the DCE12 translation unit (separate file, separate fix hunk). REG()=SEG2(0x34C0)+mm domain verified to match VBIOS full-offset storage \u2014 no finding there.", "recommended_fix": "Write *id (GPIO_ID_DDC_DATA) in every successful offset_to_id DDC-family branch (dce120 file), matching the dce80 fix." } |