# DF-3235 — procfs_docmdline() UAF read of struct pargs / lpmap / upmap

`sys/vfs/procfs/procfs_status.c` — `/proc/<pid>/cmdline`

Unprivileged local user reads another process's kernel-cached argv
(and potentially any local user's argv) out of a freed-and-recycled
kernel heap chunk, bypassing the CHECKIO / p_trespass confidentiality
gate.  Kernel heap use-after-free READ (CWE-416/CWE-125 via CWE-362).

## Build (inside the guest, as unprivileged user maxx)

    cc -O2 -Wall -pthread -o /home/maxx/racer /home/maxx/racer.c

One-time setup (also unprivileged; the reset snapshot wipes it):

    dd if=/dev/urandom of=/home/maxx/.racer_big bs=4m count=880   # 3.5GB, > RAM

## Run

    cd /home/maxx && ./racer 240 6          # seconds, #fillers

## What it does

  * `victim` (pinned cpu1): loop { exec self with small argv (~176B,
    cached in a 192-byte M_PARGS chunk); run ~0.1-1ms; exec self with a
    6KB argv (> ps_arg_cache_limit=256, so kern_exec.c FREES p_args and
    does NOT reallocate); run; repeat }.
  * `fillers` (pinned cpu1/cpu2): loop { exec self with a byte-identical-
    sized MARKER argv } — constant M_PARGS 192-byte-zone churn that
    recycles the victim's freed chunk.
  * `readers`: readv(/proc/<victim>/cmdline, 184 x 1-byte iovecs) into a
    freshly mmap'd, never-touched 4KB-strided window of the 3.5GB file.
    Every iovec copyout takes a cold page fault (real disk I/O), so the
    read blocks mid-copy for tens/hundreds of ms — dropping the LWKT
    p_token held by procfs_rw — while the victim's execve frees the pargs
    chunk the reader already snapshotted (`bp = p->p_args->ar_args`,
    procfs_status.c:241).  The later iovecs are then copied from the
    freed/recycled chunk.

## Expected output (stock kernel)

    [reader NNNN] HIT: 184B 5.27ms: /home/maxx/racer.victim.A.AAAA...FFFFF...
    RESULT: UAF-READ REPRODUCED (MARKER from recycled pargs chunk)

The 'F' tail (filler argv pad bytes) cannot legally appear in the
victim's cmdline — the victim never passes an 'F' byte.  Observed
4 torn reads across 3 stock-kernel runs (runs 12/13/15 in this pack).

## Expected output (kernel with fix.diff)

    [reader NNNN] timeout: args=NNN(slow=NNN,anom=0) ...
    RESULT: no hit within timeout

(two 300s runs, ~12k blocked p_args reads, zero anomalies)
