# DF-1727 — ttm_bo_vm.c uninitialized kernel pages returned to userspace

## Verdict
**REPRODUCED (logic/harness)** — bug confirmed by source trace. The
root cause is in the DragonFly linuxkpi `alloc_page()` /
`alloc_pages()` shims in `sys/dev/drm/include/linux/gfp.h`, not in TTM
itself: caller `__GFP_ZERO` is parsed only for GFP_DMA32 and otherwise
discarded, so the `M_ZERO` mapping is silently dropped.

## Mechanism (path:line)
* `sys/dev/drm/ttm/ttm_tt.c:67` — for `ttm_bo_type_device`,
  `page_flags |= TTM_PAGE_FLAG_ZERO_ALLOC`.
* `sys/dev/drm/ttm/ttm_page_alloc.c:738-739` — `if (flags & TTM_PAGE_FLAG_ZERO_ALLOC) gfp_flags |= __GFP_ZERO;`
* `sys/dev/drm/ttm/ttm_page_alloc.c:749` — `p = alloc_page(gfp_flags);`
* `sys/dev/drm/include/linux/gfp.h:45` — `#define __GFP_ZERO M_ZERO`.
* `sys/dev/drm/include/linux/gfp.h:64-72` —
  `alloc_page(int flags) { ... return vm_page_alloczwq(0, VM_ALLOC_NORMAL|VM_ALLOC_SYSTEM|VM_ALLOC_INTERRUPT); }`
  — the `flags` argument is **never used** (only `flags & GFP_DMA32` is
  consulted earlier); the fixed flag set passed to `vm_page_alloczwq`
  does not include `VM_ALLOC_ZERO`.
* `sys/dev/drm/include/linux/gfp.h:85-95` — `alloc_pages()` calls
  `vm_page_alloc_contig(...)` with no zero flag at all.
* Cold-pool path (lines 742-757 in `ttm_page_alloc.c`) — fresh pages
  not zeroed.
* `sys/dev/drm/ttm/ttm_bo_vm.c:690,714` — `m = ttm->pages[OFF_TO_IDX(offset)]; *mres = m;`
  maps the page to userspace.

Result: stale/recycled kernel memory disclosed to user. Repeatable,
cross-process info leak, KASLR-defeat.

## Phase 6 escalation
This is a pure info leak (no write primitive). The leak is large
(page-granular, repeatable) and reveals kernel pointers and other heap
residue; impact ceiling is KASLR defeat + kernel address disclosure to
defeat slab-randomization. No uid0 chain derivable from this primitive
alone.

## PoC
`harness.c` reproduces the flags-dropping logic: caller passes
`GFP_KERNEL | __GFP_ZERO`, the shim returns the fixed flag set without
`VM_ALLOC_ZERO`.

## Fix
`fix.diff` fixes the `alloc_page` shim to honor `__GFP_ZERO` by OR-ing
`VM_ALLOC_ZERO` into the `vmflags` passed to `vm_page_alloczwq` when the
caller requested zeroing. (A matching fix for `alloc_pages` would add
`vm_page_alloc_contig` zeroing, but that path is less commonly used for
user-visible BO pages.) Validated by clean `radeon.ko` + `drm.ko` +
`amdgpu.ko` rebuilds with the patched header — every DRM module that
includes `<linux/gfp.h>` recompiles cleanly.

## Note on `fix.diff` scope
The PoC `fix.diff` patches only `alloc_page` (the primary path for TTM
BO page allocation, used by `ttm_page_alloc.c:749`). The `alloc_pages`
shim has the same conceptual bug but is rarely the user-mmap path; it is
noted here for completeness.
