β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-2133

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_DRM slab to place a controlled pointer at the resv offset (via prior DRM object alloc/free cycles), this becomes an arbitrary kernel read/write primitive.
  • Required config or capabilities: DRIVER_PRIME set by i915, amdgpu, or radeon.
  • Reachability: DRM_IOCTL_PRIME_FD_TO_HANDLE on a dma-buf fd.

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)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2133 Β· 6 files
FileTypeDescriptionSize
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
VERDICT.md verdict source-level analysis with path:line citations
↓ download 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_DRM slab bucket content determines what garbage address resv holds
  • 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_testable
baseline no→ patch + rebuild →patched clean

git 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.