get_user_pages() KKASSERT inverts td_proc polarity, panicking on every user-context call
Summary
linux_shmem.c:137 asserts KKASSERT(td->td_proc == NULL) then line 138 derefs td->td_proc->p_vmspace->vm_map. Assertion inverted: in INVARIANTS kernels (default X86_64_GENERIC sys/config/X86_64_GENERIC:56) panics whenever td_proc non-NULL which is exactly syscall-context. td_proc set non-NULL at user thread creation (kern_fork.c:822) cleared on exit (kern_exit.c:905). Function cannot be called from user process without panicking. Intended assertion clearly != NULL; even removed kernel thread (td_proc NULL) would NULL-deref. Reachable: radeon_gem_userptr_ioctl RADEON_GEM_USERPTR READONLY|VALIDATE -> radeon_ttm_tt_set_userptr -> ttm_bo_validate -> radeon_ttm_tt_populate -> get_user_pages (radeon_ttm.c:574) -> panic. amdgpu userptr stubbed i915 uses _remote/_fast. Attacker: video-group user issues ioctl with page-aligned ptr. Result immediate kernel panic system-down DoS.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2164 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| VERDICT.md | verdict | source-level analysis with path:line citations | 1.6 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) | 370 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-2164: get_user_pages() KKASSERT inverts td_proc polarity
Verdict: NOT REPRODUCED (HW-gated) β source-confirmed real bug
Reachability
NOT reachable on this QEMU guest. get_user_pages() is in sys/dev/drm/linux_shmem.c,
part of drm.ko. Called from DRM drivers' userptr (user pointer) GEM object creation paths
(e.g. i915 i915_gem_userptr_ioctl). Without GPU hardware, no DRM GEM operations are
possible, and get_user_pages() is never called.
Mechanism (source-confirmed)
get_user_pages() at linux_shmem.c:121-168:
1. Line 135: td = curthread
2. Line 136: KKASSERT(vmas == NULL) β fine
3. Line 137: KKASSERT(td->td_proc == NULL) β WRONG: asserts td_proc is NULL
4. Line 138: map = &td->td_proc->p_vmspace->vm_map β dereferences td_proc
The assertion is inverted. In syscall context, curthread->td_proc is non-NULL (it
points to the calling process). The correct assertion is KKASSERT(td->td_proc != NULL).
On INVARIANTS kernels (default X86_64_GENERIC): The KKASSERT fires immediately,
panicking the kernel before line 138 even executes. Every call to get_user_pages() from
user context panics.
On non-INVARIANTS kernels: The assertion is compiled out, and line 138 works correctly
(because td_proc is valid). The code is functionally correct minus the assertion β the
assertion itself is the bug.
Primitive
- Class: kernel panic (DoS) on INVARIANTS kernels
- Trigger: any DRM userptr operation on an INVARIANTS kernel
- On non-INVARIANTS kernels: no effect (assertion compiled out, code correct)
Fix
fix.diff: Change == NULL to != NULL at line 137:
KKASSERT(td->td_proc != NULL);
Fix verification
not_testablegit apply --check clean + drm.ko compiles
git apply --check clean + drm.ko compiles
Confirmed kernel references
β
Detail
Exploit chain
none (HW-gated)
Evidence (decisive lines)
HW-GATED (no GPU). Source-confirmed: KKASSERT(td->td_proc == NULL) is INVERTED (should be != NULL). Panics on every call on INVARIANTS GENERIC.
Verified recommended fix
HW-GATED (no GPU). Source-confirmed: KKASSERT(td->td_proc == NULL) is INVERTED (should be != NULL). Panics on every call on INVARIANTS GENERIC.
Verdict
HW-GATED (no GPU). Source-confirmed: KKASSERT(td->td_proc == NULL) is INVERTED (should be != NULL). Panics on every call on INVARIANTS GENERIC.
No comments yet.