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

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)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2164 Β· 6 files
FileTypeDescriptionSize
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
VERDICT.md verdict source-level analysis with path:line citations
↓ download 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_testable
baseline no→ patch + rebuild →patched clean

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