# 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:
```c
KKASSERT(td->td_proc != NULL);
```
