# DF-2713 — Uninitialized cmsg tail-padding kernel heap leak via recvmsg(2)

## What
`sbcreatecontrol()` (sys/kern/uipc_sockbuf.c:585-603) builds every
kernel-generated control message (SCM_TIMESTAMP, IP_RECVDSTADDR,
IP_RECVTTL, IP_RECVTOS, IP_RECVIF, IPV6_PKTINFO, IPV6_HOPLIMIT, SCM_CREDS,
…) in a recycled plain mbuf and sets `m->m_len = CMSG_SPACE(size)`, but it
only writes `CMSG_LEN(size)` bytes (aligned header + data).  The alignment
padding bytes between `CMSG_LEN(size)` and `CMSG_SPACE(size)` are **never
initialized** and retain the stale contents of the recycled mbuf object.

`sys_recvmsg()` (sys/kern/uipc_syscalls.c:1172-1192) copies out
`m->m_len` bytes per control mbuf — padding included — into the user's
control buffer.

On x86_64 (8-byte alignment, `sizeof(struct cmsghdr)`=12, header aligned
to 16): `IP_RECVTTL`/`IP_RECVTOS` leak **7 stale bytes per packet**,
`IP_RECVDSTADDR`/`IPV6_PKTINFO`/`IPV6_HOPLIMIT` leak 4, `IP_RECVIF`
leaks 0-7 (sockaddr_dl length dependent), `SCM_CREDS` 4.

## Threat
Any unprivileged local user (no jail, no privileges): open a UDP socket,
`setsockopt(IP_RECVTTL/IP_RECVTOS/IP_RECVDSTADDR)`, exchange loopback
datagrams, `recvmsg(2)`, read the padding.  Because the control mbuf is
allocated from the global per-CPU plain-mbuf objcache, the padding
discloses **whatever any process last freed into that mbuf** — packet
payloads, control buffers, socket data of other users.  Grooming with a
failing `sendmsg(2)` (which allocates a plain `MT_CONTROL` mbuf, copies
the attacker's control bytes in, then frees it via sosend's error path,
sys/kern/uipc_socket.c:1240) makes the disclosure deterministic.

## Reproduce
```
cc -O2 -Wall -o leak_cmsgpad leak_cmsgpad.c
./leak_cmsgpad
```
Success criterion: Phase B reports MARKER(0xCC) > 0 and the marker-hit
hexdump shows `cc cc cc cc` after the `7f 00 00 01` (127.0.0.1) data of
the IP_RECVDSTADDR cmsg — bytes the kernel never wrote, copied to
userspace.  Phase C demonstrates the same with a **fork()ed process's**
0x5A marker (cross-process disclosure).

Observed on the guest (3 executions): 2396/2400/2400 (run.log),
8/4/1579 + cross-proc 4/4/4 (run.2.log), 1196/1668/2280 (run.3.log)
marker bytes per 300-receive run.

## Fix
Zero the tail padding in `sbcreatecontrol()` (see fix.diff).
