⬢ DragonFlyBSD Kernel Audit
DF-4635 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-4635",
  "status": "inconclusive",
  "reproduced": 0,
  "impact": "none",
  "confidence": "certain",
  "verdict": "Driver path is hardware-gated on this guest (no radeon GPU, no /dev/dri) so the finding could not be exercised end-to-end; however the type confusion is proven statically with exact lines (atombios_encoders.c:2860-2872 installs a 280-byte radeon_encoder_lvds as enc_priv for LCD-carrying UNIPHY encoders; radeon_audio.c:459/475-484/263-268 use it as 312-byte radeon_encoder_atom_dig, touching pin@+296/afmt@+288), and the corruption PRIMITIVE is proven live on the guest kernel: kmalloc(280) gets a 288-byte chunk with zero slack (kern_slaballoc.c zoneindex), so +288/+296 alias the ADJACENT chunk - a KLD reproduced the exact accesses, showing the OOB read returning neighbor bytes and the dig->pin=NULL write zeroing the neighbors bytes [8..16). Trigger on real hardware is unprivileged (force connector probe via DRM_IOCTL_MODE_GETCONNECTOR -> radeon_dp_detect:1765 -> radeon_audio_detect) on DCE4+ radeon laptops with eDP panels; OOB-read garbage also feeds dce6_audio_enables WREG32_ENDPOINT(pin->offset,...) wild deref.",
  "exploit_chain": "(hardware-gated, not run) spray/groom the shared 288-byte kmalloc size class so a chosen victim object sits after the lvds enc_priv allocation -> force eDP detect (unprivileged GETCONNECTOR) -> driver reads victim[8..16) as r600_audio_pin* (wild deref in dce6_audio_enable on DCE6+) and writes NULL or &rdev->audio.pin[i] over victim[8..16) -> corrupt adjacent object (list ptr/refcount-class fields) -> crash-to-UAF escalation path; deterministic 8-byte NULL write per eDP detect.",
  "evidence": "run.log (KLD: usable chunk=288, adjacent pair B-A=288, OOB read *(A+296)=0xcc.., OOB write *(A+296)=NULL zeroes victim[8..16), OOB read *(A+288)); README.md offsets (lvds=280/afmt=288/pin=296); VERDICT.md full path citations; fix_build.log (patched radeon.ko builds clean -Werror); build.log (baseline module build)",
  "kernel_refs": [
    "sys/dev/drm/radeon/radeon_audio.c:444-486",
    "sys/dev/drm/radeon/radeon_audio.c:459",
    "sys/dev/drm/radeon/radeon_audio.c:475-484",
    "sys/dev/drm/radeon/radeon_audio.c:263-268",
    "sys/dev/drm/radeon/radeon_audio.c:548-551",
    "sys/dev/drm/radeon/radeon_audio.c:632-643",
    "sys/dev/drm/radeon/atombios_encoders.c:2860-2872",
    "sys/dev/drm/radeon/radeon_encoders.c:423-445",
    "sys/dev/drm/radeon/radeon_connectors.c:1765-1768",
    "sys/dev/drm/radeon/radeon_connectors.c:1851-1858",
    "sys/dev/drm/radeon/radeon_connectors.c:2264-2268",
    "sys/dev/drm/radeon/radeon_mode.h:381-396",
    "sys/dev/drm/radeon/radeon_mode.h:427-442",
    "sys/kern/kern_slaballoc.c:638"
  ],
  "poc_changes": "seed had no runnable PoC (hardware-gated finding); wrote two new artifacts: radeon_audio_offsets.c (struct offsets from tree definitions) and aflvds.c KLD (allocator-primitive demo), plus fix.diff compile-validated by rebuilding the whole radeon.ko module on the guest",
  "attempts": 3,
  "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": 240,
  "guest_dirty": 1,
  "build_cmd": "guest: cc -O -o radeon_audio_offsets radeon_audio_offsets.c; make SYSDIR=/usr/src/sys (aflvds.ko); baseline+patched radeon.ko module builds",
  "run_cmd": "guest: ./radeon_audio_offsets; kldload ./aflvds.ko; dmesg | grep aflvds",
  "code_hash": "13c8e7dea0aeecdec7912e56e289499a3208e316df6ea2e109c138742a81cfd3",
  "notes": "Guest reset (with-src) performed after the run (aflvds.ko has no unload handler). Upstream Linux v5.2 verified byte-identical at the root-cause site - latent upstream, but cross-object corruption is DragonFly-specific due to 32-byte-granular slab zone classes. No /dev/dri on guest: DRM ioctls unrunnable; DRM_IOCTL_MODE_GETCONNECTOR would be the unprivileged trigger on real hardware.",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff applies clean (git apply --check) and the full radeon.ko module rebuilds with -Werror on the guest toolchain (fix_build.log); behavioral validation impossible on this guest - no radeon GPU to run the detect path against.",
  "fix_evidence": "fix.diff; fix_build.log (patched radeon_audio.o + radeon.ko link, exit 0)",
  "recommended_fix": "Gate radeon audio handling on encoder->encoder_type == DRM_MODE_ENCODER_TMDS in radeon_audio_detect() and radeon_audio_enable()s walk (mirroring the existing DVI-path gate), plus a dig NULL guard; see fix.diff"
}