# DF-0337 — tcp_pcblist sysctl raw-copies entire inpcb + tcpcb (info leak)

## Verdict: REPRODUCED — info leak of 113 kernel pointers to unprivileged user

## Mechanism

`tcp_pcblist()` in `sys/netinet/tcp_subr.c:1284-1293` builds the
`net.inet.tcp.pcblist` sysctl response by `bcopy()`ing the **entire**
`struct inpcb` and `struct tcpcb` into the exported `struct xtcpcb`:

```c
bcopy(inp, &xt.xt_inp, sizeof *inp);          // line 1285
bcopy(inp_ppcb, &xt.xt_tp, sizeof xt.xt_tp);  // line 1288
sotoxsocket(inp->inp_socket, &xt.xt_socket);   // line 1292
```

Only `xt_socket` is sanitized (via `sotoxsocket()`). Every other pointer
field in both structs is leaked raw:

- **inpcb** (~15 pointers): `inp_hash`/`inp_list`/`inp_portlist`
  LIST_ENTRY links, `inp_ppcb`, `inp_pcbinfo`, `inp_socket`,
  `inp_route.ro_rt`, `inp_depend4.inp4_options/moptions`,
  `inp_depend6.inp6_options/outputopts/moptions/icmp6filt`,
  `inp_porthash`, `inp_phd`, `inp_pf_sk`
- **tcpcb** (~12 pointers): `t_segq` (TAILQ_HEAD), `t_pcbport`,
  `tt_rexmt`/`tt_persist`/`tt_keep`/`tt_2msl`/`tt_delack` callouts,
  `tt_msg`, `tt_sndmore`, `t_inpcb`, `scb.sackblocks` (TAILQ_HEAD),
  `scb.lastfound`, `scb.freecache`, `t_outputq` (TAILQ_ENTRY)
- **xsocket** (2 pointers): `xso_so` and `so_pcb` —
  `sotoxsocket()` **deliberately** copies these as "convenience handles"

The sysctl is `CTLFLAG_RD` (readable by any unprivileged user).

## Proof

```
pcblist total bytes: 5480
sizeof(struct xtcpcb): 1096
records: 5
LEAK: 113 kernel-pointer-sized words in pcblist output
VERDICT: LEAK CONFIRMED (113 kernel pointers exposed to unpriv user)
```

Sample leaked pointers (3 runs, stable within a boot):
```
  rec 1 off  24: fffff80117bb8600   (inp_hash.le_next — heap)
  rec 1 off  32: ffffffff81563f90   (inp_hash.le_prev — text)
  rec 1 off 128: fffff80116d773a0   (inp_socket — heap)
  rec 1 off 256: fffff8004f102590   (inp_ppcb = tcpcb — heap)
  rec 1 off 336: fffff80116d77610   (tt_rexmt callout — heap)
  rec 1 off 928: fffff80117b3df40   (xt_socket.xso_so — heap)
  rec 1 off 1088: ffffffff811013d0  (stack residue — text addr)
```

3 stress runs: 113, 113, 113 — deterministic within a boot.

## Impact

KASLR defeat + heap-layout disclosure. On a default DragonFly kernel
(KASLR currently OFF), this directly leaks `commit_creds`,
`prepare_kernel_cred`, slab object addresses, and the layout of
adjacent heap objects — fueling further exploitation of any
memory-corruption primitive. FreeBSD removed this anti-pattern years
ago; DragonFly still ships it.

## Fix

`fix.diff` — after the `bcopy` calls, explicitly NULL every pointer
field in `xt_inp`, `xt_tp`, and `xt_socket` (including `xso_so` and
`so_pcb` which `sotoxsocket` deliberately copies). Also `bzero(&xt)`
first to kill stack residue in `xt_alignment_hack`. Validated: baseline
113 pointers → patched 0 pointers (3× each).
