# DF-0739 — ip_fw3_ctl_set_get heap over-read / kernel memory disclosure

**Severity:** Medium (info leak) · **Status:** REPRODUCED, FIX VALIDATED
**Cited bug:** `sys/net/ipfw3/ip_fw3_set.c:213` —
`bcopy(&ctx->sets, sopt->sopt_val, sopt->sopt_valsize)` with no bounds check;
`ctx->sets` is a 4-byte `uint32_t`, the LAST field of `struct ipfw3_context`.

## Build
```
./build.sh      # cc -O2 -o df0739 df0739.c
```

## Run (root only — see reachability)
```
./run.sh [readlen]      # default 256; tries readlen up to 65536
```
`run.sh` sets `net.filters_default_to_accept=1` and `kldload ipfw3` first
(idempotent), so loading the firewall does not cut off ssh.

## Expected

### Bug present (unpatched `#0` ipfw3.ko, sha256 `ca6ccfb9…`)
```
getsockopt returned <readlen> bytes (requested <readlen+4> payload after 4-byte x_header)
Over-read past ctx->sets: <readlen-4> bytes (heap residue):
  ...kernel pointers (0xffff...) and adjacent-slab strings (getty/ttyv*/csh/...)...
candidate 64-bit kernel pointers (0xffff...): N>0
```
A 128-byte request leaks ~124 bytes of heap incl. **up to 12 kernel pointers**;
a 1024-byte request leaks 1020 bytes.

### Fixed (patched ipfw3.ko, sha256 `241f263a…`)
```
getsockopt returned 4 bytes (requested <readlen+4> payload after 4-byte x_header)
ctx->sets (first 4 bytes, the only legitimate field): ...
len <= 4: no over-read observed
```
Exactly the 4 valid bytes of `ctx->sets`; zero heap residue.

## Reachability

- `ipfw3.ko` must be loaded (`kldload ipfw3`, root).
- `IP_FW_X` is handled only by `rip_ctloutput` (`sys/netinet/raw_ip.c`),
  reachable solely via `SOCK_RAW`, which needs `SYSCAP_NONET_RAW` (root).
- An unprivileged user (maxx) gets `EPERM` on `socket(SOCK_RAW,…)` and
  `ENOPROTOOPT` on `IP_FW_X` over `SOCK_DGRAM`.

**=> This is a root-reachable heap info leak, not an unpriv→root escalation.**

## Fix

`fix.diff` clamps the copy to `sizeof(ctx->sets)` (4 bytes) and sets
`sopt_valsize` so the `copyout` returns only those 4 bytes. Validated on a
rebuilt `ipfw3.ko` (module-scoped single-file fix; no kernel rebuild needed).
