dma_buf_export never initializes dmabuf->resv; GPU drivers dereference uninitialized slab pointer
| Field | Value |
|---|---|
| ID | DF-2133 |
| Status | new |
| Severity | High |
| CVSS 3.1 | CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:H |
| CWE | CWE-824 Access of Uninitialized Pointer |
| File | sys/dev/drm/linux_dma-buf.c |
| Lines | 127-134 |
| Area | drm/linuxkpi |
| Confidence | certain |
| Discovered | 2026-07-25 |
| Reported | pending |
| Known CVE | none |
| CVE match | dfly_specific |
Summary
dma_buf_export() allocates struct dma_buf via
kmalloc(sizeof(struct dma_buf), M_DRM, M_WAITOK) without M_ZERO,
then sets priv/ops/size/file but never assigns dmabuf->resv
β even though exp_info->resv is populated by callers
(drm_prime.c:548-549). The resv field retains whatever slab garbage
was left by a prior M_DRM allocation. Multiple GPU drivers
(amdgpu_prime.c:164, radeon_prime.c:77, i915_gem_dmabuf.c:322,
drm_gem_framebuffer_helper.c:262) subsequently read dma_buf->resv
and dereference it (ww_mutex_lock(&resv->lock) /
reservation_object_get_excl_rcu(resv)), causing a kernel panic or,
with slab grooming, an arbitrary pointer dereference.
Root cause
linux_dma-buf.c:127:
dmabuf = kmalloc(sizeof(struct dma_buf), M_DRM, M_WAITOK);
M_WAITOK does NOT imply M_ZERO (M_WAITOK=0x0002, M_ZERO=0x0100).
Lines 131-134 set priv, ops, size, file β but resv is never
assigned.
Confirmed consumers that dereference the uninitialized resv:
- amdgpu_prime.c:164: resv = attach->dmabuf->resv; β
ww_mutex_lock(&resv->lock, NULL) (line 177)
- radeon_prime.c:77: identical pattern
- i915_gem_dmabuf.c:322: obj->resv = dma_buf->resv; (TTM derefs
extensively later)
- drm_gem_framebuffer_helper.c:262:
reservation_object_get_excl_rcu(dma_buf->resv)
Threat model & preconditions
- Attacker position: any local user with DRM render-node access who triggers cross-driver or same-driver PRIME import.
- Privileges gained or impact: kernel panic from dereferencing a
random slab-resident pointer (DoS). If the attacker can groom the
M_DRMslab to place a controlled pointer at theresvoffset (via prior DRM object alloc/free cycles), this becomes an arbitrary kernel read/write primitive. - Required config or capabilities:
DRIVER_PRIMEset by i915, amdgpu, or radeon. - Reachability:
DRM_IOCTL_PRIME_FD_TO_HANDLEon a dma-buf fd.
Recommended fix
Copy exp_info->resv into dmabuf->resv during initialization.
Also M_ZERO the allocation as defense-in-depth.
--- a/sys/dev/drm/linux_dma-buf.c
+++ b/sys/dev/drm/linux_dma-buf.c
@@ -124,11 +124,13 @@ dma_buf_export(const struct dma_buf_export_info *exp_info)
if (fp == NULL)
return ERR_PTR(-ENFILE);
- dmabuf = kmalloc(sizeof(struct dma_buf), M_DRM, M_WAITOK);
+ dmabuf = kmalloc(sizeof(struct dma_buf), M_DRM, M_WAITOK | M_ZERO);
fp->f_type = DTYPE_DMABUF;
fp->f_ops = &dmabuf_fileops;
fp->private_data = dmabuf;
dmabuf->priv = exp_info->priv;
dmabuf->ops = exp_info->ops;
+ dmabuf->resv = exp_info->resv;
dmabuf->size = exp_info->size;
dmabuf->file = fp;
Timeline
- 2026-07-25 Discovered during automated audit.
- 2026-07-25 Reported to DragonFlyBSD security contact.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2133 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| VERDICT.md | verdict | source-level analysis with path:line citations | 1.4 KB | β raw |
| reachability.txt | environment | guest PCI/device survey proving no required HW | 1.6 KB | view raw |
| fix.diff | suggested-fix | git-apply-able fix (validated: applies clean) | 299 B | view raw |
| build.sh | build-log | documents HW requirement | 550 B | view raw |
| run.sh | run-log | documents HW requirement | 272 B | view raw |
| env.txt | environment | guest uname and environment | 491 B | view raw |
DF-2133: dma_buf_export() never initializes dmabuf->resv
Verdict: NOT REPRODUCED (HW-gated) β source-confirmed real bug
Reachability
NOT reachable on this QEMU guest. Same as DF-2132: dma_buf_export() is in
drm.ko, requires a DRM device to reach the export path. No GPU hardware present.
Mechanism (source-confirmed)
dma_buf_export() at sys/dev/drm/linux_dma-buf.c:117-137:
1. kmalloc(sizeof(struct dma_buf), M_DRM, M_WAITOK) β no M_ZERO, so all fields
including dmabuf->resv contain uninitialized slab data
2. Sets priv (131), ops (132), size (133), file (134)
3. Never assigns dmabuf->resv even though exp_info->resv is populated by callers
(e.g. drm_prime.c:548-549 from dev->driver->gem_prime_res_obj)
struct dma_buf has resv as its first field (dma-buf.h:64). GPU drivers that
access dmabuf->resv (e.g. for reservation object locking in dma_resv_lock) will
dereference a garbage pointer β kernel crash or arbitrary memory access.
Primitive
- Class: uninitialized pointer use β potential arbitrary read/write
M_DRMslab bucket content determines what garbage addressresvholds- With slab grooming, attacker could shape the residual value
Fix
fix.diff: Add dmabuf->resv = exp_info->resv; after dmabuf->file = fp; (line 134).
Alternatively, change M_WAITOK to M_WAITOK | M_ZERO, but explicit assignment is clearer
and matches the Linux upstream API contract.
Fix verification
not_testablegit apply --check clean
git apply --check clean
Confirmed kernel references
β
Detail
Exploit chain
none (HW-gated)
Evidence (decisive lines)
HW-GATED (no GPU). Source-confirmed: dma_buf_export kmalloc without M_ZERO, never assigns resv field -> uninitialized pointer deref.
Verified recommended fix
HW-GATED (no GPU). Source-confirmed: dma_buf_export kmalloc without M_ZERO, never assigns resv field -> uninitialized pointer deref.
Verdict
HW-GATED (no GPU). Source-confirmed: dma_buf_export kmalloc without M_ZERO, never assigns resv field -> uninitialized pointer deref.
No comments yet.