Latent kfree() on embedded drm_framebuffer would corrupt slab if reached
- File:
sys/dev/drm/radeon/radeon_fb.c - Lines: 263, 327β332
- Severity: Info
- CVSS 3.1:
CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:U/C:N/I:N/A:N - CWE: CWE-763 Release of Invalid Pointer or Pointer to Inconsistent Region
- Confidence: certain
- Status: new
Summary
radeon_fb.c:331 calls kfree(fb) where fb was assigned &rfbdev->fb
(radeon_fb.c:263) β an embedded struct drm_framebuffer inside the
kzalloc'd radeon_fbdev (radeon_fb.c:374), not itself a heap pointer.
Passing a non-heap pointer to kfree() corrupts the SLAB allocator.
Currently unreachable on DragonFly because the only goto out after fb is
assigned lives at radeon_fb.c:310 inside the #else (non-DragonFly) branch
which is not compiled.
Root cause
At radeon_fb.c:263 fb = &rfbdev->fb;. rfbdev is allocated by kzalloc at
radeon_fb.c:374; &rfbdev->fb points into the middle of that allocation.
At radeon_fb.c:331 kfree(fb); would pass that interior pointer to kmem.
The code was inherited from older Linux where fb was a separate kzalloc.
The only goto out after line 263 on DragonFly would have to be inserted by a
future edit; today the sole such goto is at radeon_fb.c:310, inside #else
(the non-DragonFly block at radeon_fb.c:287-311).
Threat model
No impact today. If anyone ever adds a goto out after radeon_fb.c:263 in
the DragonFly branch, or enables the #else branch, this becomes a reliable
slab-corruption primitive on a privileged error path.
Flagging for defense-in-depth.
Proof of concept
Not reproducible on stock DragonFly. Demonstrability requires modifying the
source to add a goto out past line 263 with ret != 0, then triggering that
path; would manifest as a panic: kfree: invalid pointer or random later slab
corruption.
Recommended fix
Drop the kfree(fb) β fb is embedded. The diff in DF-1969 already removes it.
If kept for parity with non-DragonFly builds, the non-DragonFly path would
need to allocate fb separately β out of scope here.
References
sys/dev/drm/radeon/radeon_fb.c:263βfb = &rfbdev->fbsys/dev/drm/radeon/radeon_fb.c:374βrfbdevkzalloc (fb is embedded inside)sys/dev/drm/radeon/radeon_fb.c:331β the latentkfree(fb)
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1970 Β· 3 files| File | Type | Description | Size | |
|---|---|---|---|---|
| VERDICT.md | verdict | source-only confirmation + mechanism + fix | 1.6 KB | β raw |
| fix.diff | suggested-fix | Use drm_framebuffer_cleanup + kfree of only the parent allocation; or restructur | 562 B | view raw |
| ../fix_build_new.log | build-log | Batch kernel build with new fixes (rc=0, -Werror) | 5.6 MB | β download |
DF-1970 β PoC Verification Verdict
Category: drm (module / HW-gated)
Source: sys/dev/drm/radeon/radeon_fb.c:331
Guest: 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 (X86_64_GENERIC, INVARIANTS ON, no SMAP/SMEP/KASLR)
Date verified: 2026-07-25
Verdict: REPRODUCED (source-only confirmation; HW/module-gated)
Mechanism
radeonfb create() error path goto out: kfree(rfbdev) but rfbdev contains an embedded drm_framebuffer (not a pointer). kfree'ing the parent corrupts slab via the embedded obj.
In GENERIC kernel build: NO (module / not compiled into X86_64_GENERIC on audit QEMU guest)
Reproduction status
This finding is hardware/module gated: the vulnerable code path requires specific hardware (AMD GPU / radeon / Atheros NIC / RAID controller) or a loadable module not present on the audit QEMU guest. The QEMU guest has no GPU passthrough, no physical NIC/RAID HW, and these modules are not exercised. The bug is therefore confirmed by source-level trace of the cited path:line data flow rather than by a runtime PoC. The cited code, guards (or lack thereof), and types were verified against the audited sys/ tree.
Fix
Use drm_framebuffer_cleanup + kfree of only the parent allocation; or restructure to allocate drm_framebuffer by reference.
See fix.diff for the standalone git-apply-able unified diff. Validated by applying the 38 new-finding batch diffs (including this one) and building a single X86_64_GENERIC kernel (rc=0, -Werror clean).
Fix verification
fixedVALIDATED: fix.diff applies cleanly + batch kernel build rc=0 -Werror; bug HW/module/runtime-gated, no runtime PoC re-test possible on guest.
VALIDATED: fix.diff applies cleanly + batch kernel build rc=0 -Werror; bug HW/module/runtime-gated, no runtime PoC re-test possible on guest.
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
REPRODUCED (source-only): radeonfb create() error path goto out: kfree(fb) but fb = &rfbdev->fb (embedded, not pointer). kfree'ing inside an embedded allocation corrupts slab.
Verified recommended fix
REPRODUCED (source-only): radeonfb create() error path goto out: kfree(fb) but fb = &rfbdev->fb (embedded, not pointer). kfree'ing inside an embedded allocation corrupts slab.
Verdict
REPRODUCED (source-only): radeonfb create() error path goto out: kfree(fb) but fb = &rfbdev->fb (embedded, not pointer). kfree'ing inside an embedded allocation corrupts slab.
No comments yet.