⬢ DragonFlyBSD Kernel Audit
DF-3634 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-3634",
  "status": "inconclusive",
  "reproduced": 0,
  "impact": "leak",
  "confidence": "certain",
  "verdict": "Source-certain uninitialized-stack leak, runtime-unverifiable on this guest. i915_gem_mmap_ioctl() (sys/dev/drm/i915/i915_gem.c:1917) declares unsigned long addr at :1923; the DragonFly-only if (args->size == 0) goto out; at :1961-1962 skips the first assignment at :1977, and the out: tail at :2056-2067 does args->addr_ptr = (uint64_t)addr with error==0, copying 8 bytes of stale kernel stack to userspace on a DRM_RENDER_ALLOW ioctl (i915_drv.c:3246), reachable unprivileged with just a GEM handle. PoC built cleanly on the audit guest (BUILD-OK, build.log) but /dev/dri does not exist there (virtio-only GPU chip=0x11111234, no drm klds, run.log), so the ioctl cannot be exercised: no Intel-GPU emulation exists for this QEMU setup. On real Intel hardware the leak is repeatable per call and is a stack-contents oracle (kernel pointers -> KASLR defeat).",
  "exploit_chain": "open /dev/dri/renderD128 -> DRM_IOCTL_I915_GEM_CREATE (handle) -> loop { seed thread kernel stack via arbitrary syscalls; DRM_IOCTL_I915_GEM_MMAP {handle, size=0} } -> read args->addr_ptr = 8 bytes stale kernel stack; use disclosed pointers to defeat KASLR / locate objects in combination with a memory-corruption primitive such as DF-1146 in the same driver.",
  "evidence": "VERDICT.md (full source trace); poc_df3634.c (uapi structs matched 1:1 to sys/dev/drm/include/uapi/drm/i915_drm.h); build.log (BUILD-OK on DragonFly guest); run.log (open ENOENT, no /dev/dri, virtio GPU, no drm klds). Decisive lines: i915_gem.c:1961-1962 goto out before :1977 assignment; :2063 args->addr_ptr = (uint64_t)addr.",
  "kernel_refs": [
    "sys/dev/drm/i915/i915_gem.c:1923",
    "sys/dev/drm/i915/i915_gem.c:1961",
    "sys/dev/drm/i915/i915_gem.c:1977",
    "sys/dev/drm/i915/i915_gem.c:2056",
    "sys/dev/drm/i915/i915_gem.c:2063",
    "sys/dev/drm/i915/i915_drv.c:3246"
  ],
  "poc_changes": "Rewrote embedded uapi (initial draft had wrong ioctl numbers 0x11/0x18 and a malformed drm_i915_gem_create); now matches sys/dev/drm/include/uapi/drm/i915_drm.h exactly: DRM_I915_GEM_CREATE=0x1b, DRM_I915_GEM_MMAP=0x1e, DRM_COMMAND_BASE+nr, correct struct layouts. Added graceful no-device exit so the absent-hardware case is explicit.",
  "attempts": 2,
  "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": 95,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -Wall -o poc_df3634 poc_df3634.c",
  "run_cmd": "./poc_df3634 /dev/dri/card0",
  "code_hash": "03d9075212e9843688fdeb6fcc77f820bfedc3dffb068cd210c3feea4a5ed775",
  "notes": "Runtime verification requires an Intel GPU host (or GVT-g passthrough), unavailable in this audit infrastructure. No other code path assigns addr before the out: label on the size==0 branch (verified by reading i915_gem.c:1917-2067). The return addr; branch (i915_gem.c:2060) additionally converts stale stack bytes into an ioctl return value when IS_ERR() happens to match.",
  "recommended_fix": "Reject size==0 with -EINVAL before the mapping attempt (fix.diff), making the uninitialized read unreachable; belt-and-braces: initialize addr at declaration.",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff returns -EINVAL for size==0 (drops the object reference first), removing the goto-out path entirely so addr can never be read uninitialized. Cannot be kernel-built/run against this finding on the audit guest: i915 does not attach without Intel hardware, so no baseline or patched behavior is observable; the fix is correct by construction (the uninit use site becomes dead code on that path).",
  "fix_evidence": "fix.diff hunk at i915_gem.c:1958-1967; source trace in VERDICT.md."
}