DF-5064 / verdict.json
{ "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" } |