# DF-0938 — `/proc/<pid>/fpregs` uninitialized kernel stack leak

## Summary

`procfs_dofpregs` (`sys/vfs/procfs/procfs_fpregs.c:54`) declares `struct fpreg r`
(512 bytes) on the kernel stack without zeroing. On the default `cpu_fxsr=true`
amd64 path, `fill_fpregs` → `fill_fpregs_xmm` writes only 108 of those 512 bytes
(env87 + sv_ac[8]). `uiomove_frombuf(&r, sizeof(r), uio)` then copies the full
512 bytes to userspace, leaking **~404 bytes of uninitialized kernel stack** —
including kernel `.text`/`.data`/heap pointers — to any local user who reads
`/proc/self/fpregs`. Pure info leak (KASLR-defeat primitive); no corruption.

## Build & run (as unprivileged user `maxx`)

```
./build.sh && ./run.sh
```

Equivalent manual invocation:
```
cc -O2 -o poc poc.c
./poc | hexdump -C | sed -n '1,40p'
```

## Expected output

**BUGGY kernel (`6.5-DEVELOPMENT #0`, unpatched):**
```
read 512 bytes
~300 non-zero non-0xAA bytes in tail [108..512) (leaked kernel stack)
```
Hexdump offsets `0x70..0x1ff` contain kernel-virtual pointers in
`0xfffff8008dxxxxxx`, `0xfffff80116xxxxxx`, `0xffffffff80xxxxxx` ranges.
Variance across runs confirms uninitialized stack (not deterministic FPU state).

**FIXED kernel (`6.5-DEVELOPMENT #1`, with `fix.diff` applied):**
```
read 512 bytes
0 non-zero non-0xAA bytes in tail [108..512) (leaked kernel stack)
```
Hexdump shows `00 00 00 ...` from offset `0x6c` onward (deterministic, 3 runs).

## Fix

`fix.diff` — adds `#include <sys/systm.h>` and `bzero(&r, sizeof(r))` immediately
after the `struct fpreg r;` declaration in `procfs_dofpregs`. Validated by
building a single-fix kernel and confirming the leak disappears (see VERDICT.md).

This supersedes the finding markdown's proposed `memset` (which omits the
required systm.h include and fails to compile under `-Werror`).
