DF-3764 / verdict.json
{ "finding_id": "DF-3764", "status": "inconclusive", "reproduced": 0, "impact": "leak", "confidence": "certain", "verdict": "r100_packet3_check() unconditionally reads payload dwords at fixed offsets (idx+1 for DRAW_VBUF/DRAW_INDX/DRAW_IMMD, up to idx+3 for the 0x23 packet) while radeon_cs_packet_parse() only validates that the packet header+count fit: pkt->idx + count + 1 < length_dw (radeon_cs.c:768). A truncated packet (count=0) placed as the last 2 dwords of the IB therefore makes the handler read ib[length_dw] - one dword past the IB chunk. radeon_get_ib_value() (radeon.h:1098) has no bounds check. On AGP systems the IB chunk is a kvmallocd array of exactly length_dw dwords (radeon_cs.c:337-346) -> 4-byte kernel heap OOB read; on PCI/PCIe it reads past the radeon_sa_bo sub-allocation (exactly length_dw*4, radeon_ib.c:60) into the shared IB pool (stale/other-process GPU commands). The OOB dword becomes track->vap_vf_cntl and, on the IMMD mismatch path, is printed to the kernel log as VAP_VF_CNTL.NUM_VERTICES %u (r100.c:2364-2367) - dmesg is world-readable, giving a repeated 16-bit heap-disclosure oracle. Same class as DF-1492 (r300) and DF-3592 (si). NOT runtime-verifiable on this guest (no ATI ASIC / radeonkms): inconclusive at runtime, certain at source level.", "exploit_chain": "", "evidence": "VERDICT.md (full narrative); df3764_oob_read.c (trigger); build.log (clean compile, cc 8.3 -Wall -O2); run.log (device absent); env.txt (guest has no radeon hw/module); fix.diff", "kernel_refs": [ "sys/dev/drm/radeon/r100.c:2013-2017 (PACKET3_3D_DRAW_VBUF reads idx+1 unvalidated)", "sys/dev/drm/radeon/r100.c:2020-2024 (PACKET3_3D_DRAW_INDX reads idx+1)", "sys/dev/drm/radeon/r100.c:1974-1984 (PACKET3_3D_DRAW_IMMD reads idx+1)", "sys/dev/drm/radeon/r100.c:1951-1972 (0x23 3D_RNDR_GEN_INDX_PRIM reads idx+1..idx+3)", "sys/dev/drm/radeon/radeon_cs.c:768 (fit check guarantees only pkt->idx+count+1 < length_dw)", "sys/dev/drm/radeon/radeon.h:1098-1105 (radeon_get_ib_value: no bounds check)", "sys/dev/drm/radeon/r100.c:2362-2368 (leak sink: DRM_ERROR prints NUM_VERTICES derived from OOB dword)" ], "poc_changes": "Re-seeded PoC from scratch: DF-style _IOWR(d, nr, type) ioctl encoding (uapi drm.h:800), self-contained uapi structs, packet builders verified against r100d.h/radeon_reg.h constants, register reachability verified against r100_reg_safe.h bitmap (102 entries).", "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": 15, "guest_dirty": 0, "build_cmd": "cc -Wall -O2 -o df3764_oob_read df3764_oob_read.c", "run_cmd": "./df3764_oob_read /dev/dri/renderD128", "code_hash": "1b7b763ce17cac6ce425cde13cd9e21dff471172310646999f94546d706189dd", "notes": "Guest is virtio-only (no ATI ASIC, no radeonkms module, no /dev/dri) - runtime execution impossible; module presence documented in env.txt. Source-level proof is line-exact. DF-1209 (vbpntr underflow) is a separate known finding and is NOT re-reported here.", "recommended_fix": "Require minimum packet counts (>=1 for DRAW_VBUF/DRAW_INDX/DRAW_IMMD, >=4 for 0x23) before fixed-offset payload reads", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff authored from line-exact source analysis; kernel-rebuild validation impossible on this guest (no target ASIC to baseline)", "fix_evidence": "fix.diff in pack" } |