# DF-2548 — kern.ttys sysctl pointer leak (re-verification)

DF-2548 is a re-verification run of the `kern.ttys` sysctl pointer-leak
finding (filed originally as DF-0006 at the same source location). The bug
remains present and unpatched in current DragonFlyBSD master DEV.

## Claim

`sysctl_kern_ttys` (`sys/kern/tty.c:2891-2921`) copies each `struct tty`
verbatim (`t = *tp;` at `tty.c:2911`) and exports it raw to userspace via
`SYSCTL_OUT(req, &t, sizeof(t))` (`tty.c:2914`). Only `t_dev` is sanitized
(`tty.c:2912-2913`). Every other pointer field — driver function pointers
(`t_oproc`/`t_stop`/`t_param`/`t_unhold`), heap object pointers
(`t_session`/`t_pgrp`/`t_sigio`/`t_sc`/`t_slsc`), clist data-buffer pointers,
the embedded `lwkt_token` (`t_ref`/`t_desc`), the embedded `kqinfo`
(`t_rkq`/`t_wkq` `ki_note`), and the `t_list` TAILQ linkage — is leaked raw
to any unprivileged local sysctl reader.

## Build & run

```
cc -O2 -o poc poc.c      # build.sh
./poc                    # run.sh — run as an UNPRIVILEGED user
```

## Expected output

**Bug present (unpatched `#0` baseline):**

```
got 3760 bytes from kern.ttys (readable as UNPRIVILEGED user)
...
  blob off   256  TEXT/FN : 0xffffffff80b8c0f0
  blob off   264  TEXT/FN : 0xffffffff806b87a0
  blob off   272  TEXT/FN : 0xffffffff80b87220
  ...
TOTAL kernel-range pointers leaked      : 102
  of which kernel .text/.rodata (FN)    : 38
  of which heap/direct-map              : 64
VERDICT: LEAK CONFIRMED
```
Exit code 0.

**Fixed kernel (`#1`):**

```
got 3760 bytes from kern.ttys (readable as UNPRIVILEGED user)
...
TOTAL kernel-range pointers leaked      : 0
  of which kernel .text/.rodata (FN)    : 0
  of which heap/direct-map              : 0
VERDICT: NO LEAK — pointer fields are sanitized (fixed kernel).
```
Exit code 2.

## Preconditions

- Any local user (uid 1001 `maxx`, not in `wheel`, used in this verification).
- No sysctl, mount, module, or privilege required — `kern.ttys` is a plain
  `CTLFLAG_RD` OID and `sysctl_root` does not privilege-gate reads.

## Files

| file | what |
|------|------|
| `poc.c` | minimal sysctl(2) reader; scans blob for kernel-range pointers |
| `build.sh` | `cc -O2 -o poc poc.c` |
| `run.sh` | `./poc` as the unprivileged user |
| `build.log` | final successful build output |
| `run.log`, `run.2.log`, `run.3.log` | 3 consecutive baseline runs (deterministic 102 ptrs) |
| `fix_run.log` | patched-kernel run (0 pointers) |
| `fix_build.log` | single-fix kernel build output (`make nativekernel`, rc=0) |
| `fix.diff` | git-apply-able unified diff sanitizing all pointer fields |
| `leak_sample.txt` | raw leaked pointers + cross-reference + 3-run variance |
| `env.txt` | guest uname, cc version, sysctl OID description |
| `ttys.bin` | raw 3760-byte kern.ttys blob (unpatched baseline) |
| `VERDICT.md` | full narrative analysis |
| `manifest.json` | machine-readable catalog |
