⬢ DragonFlyBSD Kernel Audit
DF-4878 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-4878",
  "status": "untested",
  "reproduced": 0,
  "impact": "none",
  "confidence": "likely",
  "verdict": "dal_i2caux_release_engine() runs unsynchronized (the DAL2 mutex was dropped \u2014 i2caux.h:91) and stores engine->ddc = NULL two statements after dal_ddc_close(); a concurrent acquirer of the same per-line engine can open the just-closed pins and install its ddc pointer inside that window, which the release then wipes \u2014 the SW-i2c submit path dereferences the NULL ddc immediately, and the AUX path ends in dal_ddc_close(NULL) whose callee dereferences ddc->pin_clock without a NULL guard (gpio_service.c:587-590) -> fatal trap. Narrow-window display-path panic; not runnable on the audit guest because its only VGA is QEMU std VGA so amdgpu never attaches.",
  "exploit_chain": "T1 release between dal_ddc_close (i2caux.c:426) and engine->ddc=NULL (:428) while T2 acquire passes the now-clear pin-open guard (gpio_base.c:59-70) and sets engine->ddc=ddc (aux_engine.c:75 / i2c_sw_engine.c:473) -> T1 wipes it -> T2 submits (SW: i2c_sw_engine.c:491 NULL ddc) or T2 releases (i2caux.c:426 dal_ddc_close(NULL) -> gpio_service.c:590 NULL deref) -> panic",
  "evidence": "VERDICT.md (interleaving with every load/store cited); README.md; env.txt (vgapci0 8086:1111 std VGA, amdgpu.ko unloaded)",
  "kernel_refs": [
    "sys/dev/drm/amd/display/dc/i2caux/i2caux.c:420",
    "sys/dev/drm/amd/display/dc/i2caux/i2caux.c:426",
    "sys/dev/drm/amd/display/dc/i2caux/i2caux.c:428",
    "sys/dev/drm/amd/display/dc/i2caux/i2caux.h:91",
    "sys/dev/drm/amd/display/dc/i2caux/aux_engine.c:75",
    "sys/dev/drm/amd/display/dc/i2caux/i2c_sw_engine.c:473",
    "sys/dev/drm/amd/display/dc/i2caux/i2c_sw_engine.c:491",
    "sys/dev/drm/amd/display/dc/gpio/gpio_service.c:587",
    "sys/dev/drm/amd/display/dc/gpio/gpio_base.c:59"
  ],
  "poc_changes": "n/a \u2014 no AMD GPU on guest (hardware blocker); race proven by code layout",
  "attempts": 0,
  "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": 0,
  "guest_dirty": 0,
  "build_cmd": "",
  "run_cmd": "",
  "code_hash": "",
  "notes": "Sinks are panic-only (wiped value is NULL); the wrong-owner-close variant (T1 closes T2s pins mid-transaction) corrupts gpio pin state but is not a controlled write. dce110s unsynchronized i2c_hw_buffer_in_use check-then-act (i2caux_dce110.c acquire_i2c_hw_engine) is the same missing-mutex family but lives in a different file (DF-4808 adjacent).",
  "recommended_fix": "Guard dal_ddc_close(engine->ddc) against NULL (sink fix, fix.diff) and restore the DAL2 per-i2caux mutex across acquire->submit->release (root fix)",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "No AMD GPU on guest; the guarded close removes the panic sink by construction; full serialization needs the mutex (recommended in finding)",
  "fix_evidence": "fix.diff (git apply --check OK)"
}