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

shem_read_mapping_page() leaks VM_OBJECT_LOCK and hold_count on every error path

Summary

shem_read_mapping_page() acquires VM object lock at line 52 via VM_OBJECT_LOCK(object) (=vm_object_hold which does refcount_acquire(hold_count)+lwkt_gettoken). All 4 error-return paths (lines 57 60 70 73) return ERR_PTR(-ENOMEM) WITHOUT calling VM_OBJECT_UNLOCK. Permanent lwkt_token hold + permanent hold_count bump: every subsequent thread touching object blocks forever; object never freed hold_count never reaches zero. Reachable on memory pressure from any GEM/shmem user. i915 caller i915_gem.c:305-317 compounds by pre-locking then only unlocking once on err_phys. Attacker: unprivileged user drives OOM via mmap/mlock/large GEM objects; first error path fires VM object wedged permanently; later operations (pinning munmap teardown destroy) block forever D-state; hold_count leak prevents reclaim repeated triggers accumulate stuck threads eventually full system hang.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2165 Β· 6 files
FileTypeDescriptionSize
VERDICT.md verdict source-level analysis with path:line citations 1.9 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) 886 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-2165: shmem_read_mapping_page() leaks VM_OBJECT_LOCK on every error path

Verdict: NOT REPRODUCED (HW-gated) β€” source-confirmed real bug

Reachability

NOT reachable on this QEMU guest. shmem_read_mapping_page() is in sys/dev/drm/linux_shmem.c, part of drm.ko. Called from DRM drivers' GEM object page management (e.g. pagecache_write_begin, i915 GEM backing-store). Without GPU hardware, these paths are unreachable.

Mechanism (source-confirmed)

shmem_read_mapping_page() at linux_shmem.c:46-87: 1. Line 52: VM_OBJECT_LOCK(object) β€” acquires VM object lock (refcount + token) 2. Four error-return paths return ERR_PTR(-ENOMEM) WITHOUT calling VM_OBJECT_UNLOCK: - Line 57: if (m == NULL) return ERR_PTR(-ENOMEM); (OBJT_MGTDEVICE path) - Line 60: if (rv != VM_PAGER_OK) { vm_page_free(m); return ERR_PTR(-ENOMEM); } - Line 70: if (m == NULL) return ERR_PTR(-ENOMEM); (normal path, lookup failed) - Line 73: if (rv != VM_PAGER_OK) { vm_page_free(m); return ERR_PTR(-ENOMEM); } 3. Line 84: VM_OBJECT_UNLOCK(object) β€” only reached on the success path

Each error return permanently leaks: - The VM object lockmgr token (permanently held β†’ blocks all VM object operations) - hold_count increment (never decremented β†’ object never freed) - May exhaust token pool or cause permanent hangs

Under memory pressure (when vm_pager_get_page fails), this bug triggers reliably, progressively locking VM objects until the system hangs.

Primitive

  • Class: resource leak (lock + refcount) β†’ progressive system degradation β†’ DoS
  • Each error path leaks one VM object lock permanently
  • Under memory pressure, multiple objects get locked β†’ system-wide hang

Fix

fix.diff: Add VM_OBJECT_UNLOCK(object); before each of the four return ERR_PTR(-ENOMEM); statements. Also adds braces to the single-line if statements to properly scope the unlock.

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: shmem_read_mapping_page 4 error paths return ERR_PTR without VM_OBJECT_UNLOCK -> lock leak.

Verified recommended fix

HW-GATED (no GPU). Source-confirmed: shmem_read_mapping_page 4 error paths return ERR_PTR without VM_OBJECT_UNLOCK -> lock leak.

Verdict

HW-GATED (no GPU). Source-confirmed: shmem_read_mapping_page 4 error paths return ERR_PTR without VM_OBJECT_UNLOCK -> lock leak.