⬢ DragonFlyBSD Kernel Audit
DF-5064 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5064",
  "status": "not_reproduced",
  "reproduced": false,
  "impact": "none",
  "confidence": "certain",
  "verdict": "drm_device_detach() (sys/dev/drm/drm_dragonfly.c:251-295), the only newbus device_detach for i915/radeon/amdgpu, never calls drm_dev_unregister() or drm_dev_put() -- unlike Linuxs i915_pci_remove() (i915_pci.c:680-691: i915_driver_unload + drm_dev_put) whose role it replaces. After kldunload of the kms module (drm.ko stays resident via MODULE_DEPEND), the /dev/dri/cardN + renderDN cdevs (drm_sysfs.c:97) remain live and drm_minor_acquire (drm_drv.c:274-282) still resolves the never-unregistered minors, so any unprivileged open/ioctl dispatches through dev->driver->* and dev->dev_private -- memory of the UNLOADED driver module (UAF-class). The whole drm_device graph also leaks per load/unload cycle, and for i915 (whose struct drm_driver has no .unload on DF, i915_drv.c:3279-3313) no driver teardown runs at all. Not executable on the audit guest (no display-class PCI adapter; /dev/dri absent -- env.txt), so verified by complete static trace; the fix (drm_dev_unregister + drm_dev_put at detach) compiles clean across the whole drm tree on the guest (fix_build.log, rc=0, drm.ko + i915.ko linked).",
  "exploit_chain": "root: kldunload i915kms (drm.ko stays) -> /dev/dri/card0 still openable 0666 -> unprivileged open -> drm_open -> drm_minor_acquire succeeds (minor never unregistered) -> dev->driver->open = i915_driver_open in freed module text -> execution through freed kernel memory (plus unbounded drm_device leak per kldload/kldunload cycle)",
  "evidence": "VERDICT.md (full path:line trace: drm_dragonfly.c:251-295, i915_pci.c:680-691/880/893, drm_drv.c:236-258/274-282/744-756/941-970, drm_sysfs.c:97, i915_drv.c:1828/3279-3313); env.txt (no display-class PCI device, /dev/dri absent on the audit guest); fix_build.log (whole-tree build rc=0 with the patch)",
  "kernel_refs": [
    "sys/dev/drm/drm_dragonfly.c:250-296",
    "sys/dev/drm/drm_dragonfly.c:164-176",
    "sys/dev/drm/i915/i915_pci.c:680-691",
    "sys/dev/drm/i915/i915_pci.c:880",
    "sys/dev/drm/i915/i915_drv.c:3279-3313",
    "sys/dev/drm/drm_drv.c:236-258",
    "sys/dev/drm/drm_drv.c:274-282",
    "sys/dev/drm/drm_drv.c:744-756",
    "sys/dev/drm/drm_sysfs.c:84-113"
  ],
  "poc_changes": "no seed; runtime PoC impossible on the audit guest (QEMU exposes no Intel/AMD/Radeon GPU and the DF drm tree has no virtio/vmwgfx/bochs driver to bind a QEMU device -- verified: sys/dev/drm contains only i915/radeon/amdgpu backends), so the evidence pack carries the static trace plus a compile-validated fix instead",
  "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": 30,
  "guest_dirty": 0,
  "build_cmd": "(fix compile-validation on guest) cp patched drm_dragonfly.c into /usr/src/sys/dev/drm; cd /usr/src/sys/dev/drm && make   # rc=0, drm.ko + i915.ko linked",
  "run_cmd": "(not runnable: no DRM adapter on the guest -- pciconf shows no class=display, /dev/dri absent; see env.txt)",
  "code_hash": "5bc6f7b3e43e40c2646d94ed89606cdd5dd95720d44d012fc62a6995319103b7",
  "notes": "Severity Medium (not High): the UAF is unprivileged-triggerable but only after a root kldunload on GPU-equipped hardware. Residual after fix: the /dev/dri dirent/cdev itself is never destroy_deved on DF (no destroy_dev anywhere in the drm tree) -- after unregister, opens fail ENODEV cleanly, which removes the UAF; node cleanup is cosmetic. i915 additionally needs a .unload hook (i915_driver_unload exists at i915_drv.c:1828) for full teardown parity -- noted in fix.diff.",
  "recommended_fix": "drm_device_detach(): call drm_dev_unregister(dev) then drm_dev_put(dev) after drm_fini_pdev(&dev->pdev), mirroring i915_pci_remove(); give i915 a .unload hook (see fix.diff)",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Fix compiles clean against the entire drm tree on the guest (make rc=0; drm.ko and i915.ko link -- fix_build.log) and matches the proven-correct Linux teardown order (i915_pci_remove). Runtime validation requires a DRM adapter, which the QEMU audit guest cannot provide (no emulated Intel/AMD GPU binds any DF drm driver); marked not_testable rather than guessing.",
  "fix_evidence": "findings/poc/DF-5064/fix_build.log (full build log, BUILD_RC=0, drm.ko + i915.ko linked with the patched drm_dragonfly.c); fix.diff"
}