# DF-2838 — sotoxsocket()/ssbtoxsockbuf() leave struct padding uninitialized → kernel stack bytes leaked via net.inet.tcp.pcblist

## What

`sys/kern/uipc_socket2.c:827-848` (`sotoxsocket`) fills every *named* field
of `struct xsocket` but never the structure padding; likewise
`ssbtoxsockbuf()` (lines 188-198) for `struct xsockbuf`. On amd64:

* `struct xsockbuf` = 46 content bytes, tail-padded to 48 → **2 uninitialized
  bytes per sockbuf** (after `short sb_flags`)
* `struct xsocket` = 164 content bytes, tail-padded to 168 → **4 uninitialized
  bytes** (after `uid_t so_uid`)

`tcp_pcblist_sysctl()` (sys/netinet/tcp_subr.c ~1265) uses a stack
`struct xtcpcb xt;` that is **never zeroed**, calls `sotoxsocket()`, and
`SYSCTL_OUT`s the whole record to any unprivileged reader of
`net.inet.tcp.pcblist` (world-readable; `netstat` source). Result: 8 stale
kernel-stack bytes per TCP pcb record reach userland.
(`sys/netinet/in_pcb.c:2467` pre-zeroes its buffer, so only the tcp pcblist
path leaks; the unix variant was already filed as DF-2558.)

## Impact

Unprivileged local info leak of limited kernel memory (kernel stack
residue). Demonstrated values include `0xfffff801` — the **upper half of a
kernel text/data pointer** (`0xfffff801xxxxxxxx` is DragonFly's kernel
address range) — varying across runs. On KASLR-enabled deployments this is
one of the two halves an attacker needs; contents are incidental stack
garbage, so the leak is limited but real. Low severity.

## Reproduce (unprivileged)

```
cc -O -D_KERNEL_STRUCTURES -include /usr/include/stdint.h \
   -I/usr/src/sys -I/usr/src/sys/sys -o pcbleak pcbleak.c
./pcbleak
```

The program dumps exactly the three pad regions for every pcblist record,
three times, churning TCP connections between passes to dirty the sysctl
thread's stack.

Observed (stock kernel, see run.log / run.2.log / run.3.log):

```
rec#0 pads: rcv=ffff snd=0000 tail=fffff801
...
run 3: tail=00000000
```

`rcv` pad constant `0xffff`, `xsocket` tail pad `fffff801` (kernel pointer
upper half) in runs 1-2, zeroed by chance in run 3 — nonzero kernel-stack
bytes in ≥2 of 3 runs, pattern matches kernel pointers.

## Files

* `pcbleak.c`, `build.sh`, `run.sh`
* `run.log`, `run.2.log`, `run.3.log` — three decisive runs (stock kernel)
* `fix_validation.log` — same PoC on the one-fix kernel (DF-2836+DF-2838
  both applied): all pads zero
* `fix.diff` — proposed fix (validated in-guest)
* `env.txt`
