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