⬢ DragonFlyBSD Kernel Audit
DF-4946 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-4946",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "dos",
  "confidence": "certain",
  "verdict": "The DCN10 copy of offset_to_id (hw_translate_dcn10.c:165-189) has the family defect of DF-4943/DF-4945: all eight DDC-family branches (DDC1-6, DDCVGA, I2CPAD) return true after writing only *en \u2014 *id is never assigned. dal_gpio_service_create_irq (gpio_service.c:148-156) declares enum gpio_id id; uninitialized and switches on the garbage value in dal_gpio_create_irq; garbage==GPIO_ID_HPD(3) with the DDC-line en of 6 (DDC_VGA) or 7 (I2C_PAD) reaches define_hpd_registers, which indexes the 6-entry hpd_regs[] (hw_factory_dcn10.c:71-78,149-157) out of bounds \u2014 garbage register descriptors then drive MMIO (hw_hpd/hw_gpio open path). Executed on the DF guest with a verbatim copy of the dcn10 function and real DCN10 constants (REG(DDCVGA)=0x5da9, REG(I2CPAD)=0x5dc1 \u2014 run.log T1: both return true with *id untouched; en=6/7 exceed hpd_regs). Kernel-stage execution requires a Raven-class ASIC + crafted VBIOS gpio_pin_lut (absent in QEMU: 0 AMD devices). Unlike dce80 there is no GPIOPAD case (T2 negative control), so no deterministic DF-4942 producer exists on DCN10; the primary dal_gpio_create_ddc consumer ignores id and its en 0..7 are in-bounds against the 8-entry ddc arrays \u2014 the uninit-id path via the HPD IRQ route is the only OOB route and is probabilistic.",
  "exploit_chain": "crafted VBIOS gpio_pin_lut v2.1 (data_a_reg_index = REG(DC_GPIO_DDCVGA_A)=0x5da9 or REG(DC_GPIO_I2CPAD_A)=0x5dc1, 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 -> hw_gpio/hw_hpd MMIO at garbage offsets -> wrong-register programming/panic. Probabilistic final stage; no unpriv-user local route (requires GPU VBIOS control).",
  "evidence": "run.log T1: offset_to_id(REG(DDCVGA),0x100) = true en=6(id==0x7b7b7b7b UNTOUCHED) and (REG(I2CPAD),0x100) = true en=7(id==0x7b7b7b7b UNTOUCHED) with the hpd_regs[6]/[7] OOB annotations; T2: 0x183 rejected (no GPIOPAD mapping \u2014 dce80-style producer absent); T4: HPD branch well-formed; fixrun section: harness_fixed reports id=0 WRITTEN on all 8 and 0 residual violations.",
  "kernel_refs": [
    "sys/dev/drm/amd/display/dc/gpio/dcn10/hw_translate_dcn10.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/dcn10/hw_factory_dcn10.c:71",
    "sys/dev/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.c:149",
    "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 dcn10 offset_to_id + id_to_offset copies, real DCN10 constants: SEG2 base 0x34C0, mmDC_GPIO_DDC1_A=0x28d1 .. I2CPAD_A=0x2901, all BASE_IDX 2).",
  "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": 5,
  "guest_dirty": 0,
  "build_cmd": "gcc -O2 -Wall -Wextra -o harness_dcn10 harness_dcn10.c && gcc -O2 -Wall -Wextra -o harness_fixed harness_fixed.c",
  "run_cmd": "./harness_dcn10; ./harness_fixed",
  "code_hash": "a23b7dbca3880b192ee5a9bb47e14842f2573511dc54e0ed41e30c93d33873f5",
  "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 dcn10 offset_to_id; harness_fixed applies the identical edit to the embedded copy and demonstrates the uninitialized id is structurally eliminated (all 8 report id=0 WRITTEN) \u2014 with id==GPIO_ID_DDC_DATA, dal_gpio_create_irq (gpio_service.c:373-381) returns NULL, so define_hpd_registers can never see en=6/7: 0 residual violations (FIXEXIT=0). A kernel rebuild cannot change userland unit-harness output; structural validation matches the family precedent (DF-4943/4945).",
  "fix_evidence": "fix.diff (hw_translate_dcn10.c hunks); run.log FIXED T1 section; harness_fixed.c e781a6d68365136864cb903683e6274e967e24514209508af01df7665cd3cc0d.",
  "notes": "Sibling of DF-4943 (dce80) / DF-4945 (dce120) in the DCN10 translation unit (separate file, separate fix hunk). Negative results recorded: no GPIOPAD case (DF-4942 producer absent), ddc arrays sized 8 == number_of_pins == GPIO_DDC_LINE_COUNT (no DF-4827 shape), HPD 0..5 == hpd_regs[6] (well-formed).",
  "recommended_fix": "Write *id (GPIO_ID_DDC_DATA) in every successful offset_to_id DDC-family branch (dcn10 file), matching the validated dce80/dce120 family fix."
}