⬢ DragonFlyBSD Kernel Audit
DF-4943 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-4943",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "dos",
  "confidence": "certain",
  "verdict": "All eight DDC-family branches of offset_to_id (hw_translate_dce80.c:172-196) return true after writing only *en; dal_gpio_service_create_irq (gpio_service.c:148-156) then feeds the never-written id into dal_gpio_create_irqs switch \u2014 a use of an uninitialized stack variable (CWE-457). Reproduced on the DF guest with the verbatim function copy: a poisoned id survives a successful offset_to_id(mmDC_GPIO_DDCVGA_A/I2CPAD/DDC1) call (run.log T1). If the indeterminate slot holds GPIO_ID_HPD(3), a DDC-line en of 6/7 reaches define_hpd_registers, which indexes hpd_regs[6] \u2014 an OOB const-array read (array has 6 entries, hw_factory_dce80.c:61-68,143) whose garbage descriptors then drive MMIO (hw_hpd.c:89,110); id_to_offsets own en>=6 rejection (harness T5) sits off the open path and does not intercept it. Kernel-stage execution requires an AMD ASIC + crafted VBIOS (absent in QEMU); the uninitialized-write contract violation itself is proven by execution.",
  "exploit_chain": "crafted VBIOS GPIO pin LUT (usGpioPin_AIndex = a DDC register offset, bios_parser.c:1819) -> get_hpd_gpio (dc_link.c:115) -> dal_gpio_service_create_irq -> offset_to_id true, id UNWRITTEN -> switch on garbage id -> garbage==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 (stack-garbage dependent).",
  "evidence": "run.log T1: three DDC offsets each return true with id left at the poison value (*id NEVER WRITTEN); T5: id_to_offset(HPD,en=6)=false proves the only route for HPD en>=6 into hpd_regs[] is the uninitialized-id path; fixrun.log: after fix, *id==GPIO_ID_DDC_DATA on all DDC decodes.",
  "kernel_refs": [
    "sys/dev/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.c:172",
    "sys/dev/drm/amd/display/dc/gpio/gpio_service.c:148",
    "sys/dev/drm/amd/display/dc/gpio/gpio_service.c:156",
    "sys/dev/drm/amd/display/dc/gpio/gpio_service.c:366",
    "sys/dev/drm/amd/display/dc/gpio/dce80/hw_factory_dce80.c:61",
    "sys/dev/drm/amd/display/dc/gpio/dce80/hw_factory_dce80.c:143",
    "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_parser.c:1819"
  ],
  "poc_changes": "n/a \u2014 fresh harness (verbatim function copy, real constants).",
  "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": 8,
  "guest_dirty": 0,
  "build_cmd": "gcc -O2 -Wall -Wextra -o harness_dce80 harness_dce80.c",
  "run_cmd": "./harness_dce80",
  "code_hash": "8df7d21c82ff5c569875602af619df7050af7a55a26992ab957c8f557669120c",
  "fix_status": "validated",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff sets *id=GPIO_ID_DDC_DATA in every DDC-family branch of offset_to_id, so the consumers id is always initialized on success (fixrun.log: -> FIXED: *id now written (GPIO_ID_DDC_DATA), consumer guard accepts); dal_gpio_create_irqs switch then deterministically rejects DDC decodes; 0 regressions.",
  "fix_evidence": "fixrun.log T1 section; fix.diff hunk 1 (eight +\t\t*id = GPIO_ID_DDC_DATA; lines).",
  "notes": "Companion defect in the DCE12 copy filed as DF-4945. Kernel-path execution impossible on this guest (no AMD ASIC \u2014 env.txt).",
  "recommended_fix": "Write *id (GPIO_ID_DDC_DATA) in every successful offset_to_id DDC-family branch so no consumer can observe an uninitialized id."
}