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)
PoC verification
Evidence pack
findings/poc/DF-2165 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| 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 |
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_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: 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.
No comments yet.