r100_cs_track_cube() NULL-pointer dereference via unbound cube-face BOs -> kernel panic from unprivileged CS ioctl (pre-R300)
Summary
r100_cs_track_cube() calls radeon_bo_size(cube_robj) for faces 0..4 with no NULL check. On r1xx/r2xx (separate_cube=1) cube-face BOs are only bound via PP_CUBIC_OFFSET_Tx_F writes; r100_cs_track_clear() NULLs all five. A DRM-authenticated local user enables a cubemap texture (CUBIC_MAP_ENABLE), binds the primary texture with reloc, enables the unit, then submits any draw reaching the validator -> radeon_bo_size(NULL) read -> kernel panic. Primary textures[u].robj IS checked but cube faces are not. Local unprivileged user with GPU access on r100..rv280/r200-class hardware crashes the kernel instantly (CS ioctl is DRM_AUTH|DRM_RENDER_ALLOW). Full raw-ioctl PoC written (builds clean); virtio-only guest -> inconclusive at runtime, certain at source. Identical defect still present in upstream Linux master (checked).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3763 Β· 10 files| File | Type | Description | Size | |
|---|---|---|---|---|
| df3763_cube_null.c | β | 5.9 KB | view raw | |
| build.sh | β | 106 B | view raw | |
| run.sh | β | 119 B | view raw | |
| build.log | β | 221 B | view raw | |
| run.log | β | 266 B | view raw | |
| env.txt | β | 595 B | view raw | |
| fix.diff | β | 424 B | view raw | |
| VERDICT.md | β | 2.8 KB | β raw | |
| manifest.json | β | 1.1 KB | view raw | |
| verdict.json | β | 3.3 KB | view raw |
DF-3763 - VERDICT
status: inconclusive (runtime) | reproduced: 0 | impact (expected): panic | confidence: certain (source)
What was verified
r100_cs_track_cube() dereferences track->textures[idx].cube_info[face].robj via radeon_bo_size() for faces 0..4 without any NULL check. On r1xx/r2xx (separate_cube=1, r100.c:2400) cube-face BOs are only bound by writing PP_CUBIC_OFFSET_Tx_F registers; track_clear() NULLs all five (r100.c:2453). An authenticated DRI client that enables a cubemap texture (PP_TXFORMAT_0 CUBIC_MAP_ENABLE -> tex_coord_type=2, r100.c:1842), binds the primary texture (PP_TXOFFSET_0 + reloc) and unit enable (PP_CNTL), then submits any draw packet that reaches the texture validator (r100_cs_track_texture_check -> r100_cs_track_cube at r100.c:2226) causes radeon_bo_size(NULL) -> kernel NULL-deref read -> panic. Deterministic, unprivileged-with-GPU-access, pre-R300 only. Identical code is still present in upstream Linux torvalds master (fetched 2026-09-16). NOT executable on the audit guest: QEMU/virtio has no ATI ASIC and no radeonkms module exists (checked: kldstat, /boot/kernel, /boot/modules, /dev/dri, pciconf) - verdict inconclusive at runtime, certain at source level.
Kernel references
- sys/dev/drm/radeon/r100.c:2134-2163 (r100_cs_track_cube, no NULL check on cube_info[face].robj)
- sys/dev/drm/radeon/r100.c:2225-2228 (separate_cube path reaches it)
- sys/dev/drm/radeon/r100.c:1842-1843 (CUBIC_MAP_ENABLE sets tex_coord_type=2)
- sys/dev/drm/radeon/r100.c:2451-2457 (cube_info[face].robj initialized NULL and never required)
- sys/dev/drm/radeon/r100.c:2400 (separate_cube=1 for all pre-R300 asics)
- sys/dev/drm/radeon/radeon_kms.c:912 (CS ioctl gate: DRM_AUTH|DRM_RENDER_ALLOW)
Why not reproduced on the guest
Guest = DragonFly 6.5-DEVELOPMENT x86_64 under QEMU (virtio-only): - kldstat: only kernel + ehci.ko + xhci.ko (drm.ko exists in /boot/kernel but is not loaded and there is no radeonkms.ko anywhere) - /dev/dri does not exist - pciconf shows no vendor-1002 (ATI) device => The radeon CS ioctl path cannot execute. The finding is proven by line-exact source analysis (integer identities / NULL flow), and the PoC is proven to build (build.log, cc 8.3 -Wall -O2, zero warnings).
Upstream comparison
Checked against Linux torvalds master r100.c (fetched 2026-09-16): identical NULL deref present upstream (equivalent).
Fix
fix.diff in this directory (not applied to the read-only sys/ tree; kernel rebuild validation not possible - no target ASIC).
Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
Fix verification
not_testablefix.diff authored from line-exact source analysis; kernel-rebuild validation impossible on this guest (no target ASIC to baseline)
fix.diff in pack
Confirmed kernel references
- sys/dev/drm/radeon/r100.c:2134-2163 (r100_cs_track_cube, no NULL check on cube_info[face].robj)
- sys/dev/drm/radeon/r100.c:2225-2228 (separate_cube path reaches it)
- sys/dev/drm/radeon/r100.c:1842-1843 (CUBIC_MAP_ENABLE sets tex_coord_type=2)
- sys/dev/drm/radeon/r100.c:2451-2457 (cube_info[face].robj initialized NULL and never required)
- sys/dev/drm/radeon/r100.c:2400 (separate_cube=1 for all pre-R300 asics)
- sys/dev/drm/radeon/radeon_kms.c:912 (CS ioctl gate: DRM_AUTH|DRM_RENDER_ALLOW)
Detail
Evidence (decisive lines)
VERDICT.md (full narrative); df3763_cube_null.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
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).
Verified recommended fix
Reject CS with -EINVAL when any of the 5 cube-face BOs is unbound in r100_cs_track_cube()
Verdict
r100_cs_track_cube() dereferences track->textures[idx].cube_info[face].robj via radeon_bo_size() for faces 0..4 without any NULL check. On r1xx/r2xx (separate_cube=1, r100.c:2400) cube-face BOs are only bound by writing PP_CUBIC_OFFSET_Tx_F registers; track_clear() NULLs all five (r100.c:2453). An authenticated DRI client that enables a cubemap texture (PP_TXFORMAT_0 CUBIC_MAP_ENABLE -> tex_coord_type=2, r100.c:1842), binds the primary texture (PP_TXOFFSET_0 + reloc) and unit enable (PP_CNTL), then submits any draw packet that reaches the texture validator (r100_cs_track_texture_check -> r100_cs_track_cube at r100.c:2226) causes radeon_bo_size(NULL) -> kernel NULL-deref read -> panic. Deterministic, unprivileged-with-GPU-access, pre-R300 only. Identical code is still present in upstream Linux torvalds master (fetched 2026-09-16). NOT executable on the audit guest: QEMU/virtio has no ATI ASIC and no radeonkms module exists (checked: kldstat, /boot/kernel, /boot/modules, /dev/dri, pciconf) - verdict inconclusive at runtime, certain at source level.
No comments yet.