# DF-3452 — Uninitialized kernel stack transmitted in ipfw3 sync datagrams (`ip_fw3_sync_send_state`)

## What

`sys/net/ipfw3_basic/ip_fw3_sync.c:437-467` — `ip_fw3_sync_send_state()`
declares `struct cmd_send_state cmd;` on the kernel stack and initializes
ONLY `cmd.type`, `cmd.cpu`, `cmd.hash` (lines 448-450). The remaining
fields — `struct ipfw_flow_id flow` (14 bytes: dst_ip, src_ip, dst_port,
src_port, proto, flags), `uint32_t expiry`, `uint16_t lifetime`,
`int rulenum` — are uninitialized stack garbage. The full struct is then
`memcpy`'d into an mbuf (`memcpy(m->m_data, &cmd, len)`, line 452) and
sent to every configured sync edge over UDP
(`so_pru_sosend(fw3_sync_ctx.centre_socks[i], ...)`, lines 458-465).

If the ipfw3 state-sync sender were wired up, every synced state entry
would disclose ~28 bytes of kernel stack to the UDP peer(s) configured
in `fw3_sync_ctx.edges` — a remote kernel-stack info disclosure
(CWE-908 / CWE-209), reusable for KASLR-style defeat of stack canaries /
pointer obfuscation on the syncing host.

## Reachability (why this is latent)

The function is currently DEAD CODE, twice over:

1. The socket-option path is dead: `ip_fw3_ctl_sync_ptr` (the function
   pointer that routes IP_FW_SYNC_* socket options to
   `ip_fw3_ctl_sync_sockopt`) is declared NULL in
   sys/net/ipfw3/ip_fw3.c:133 and is NEVER assigned anywhere in the
   tree — the sync case in `ip_fw3_ctl()` (ip_fw3.c:1124-1128) checks
   it and silently does nothing. Contrast `ip_fw3_ctl_state_ptr`
   (assigned at ip_fw3_state.c:699) and `ip_fw3_ctl_table_ptr`
   (ip_fw3_table.c:608), which ARE assigned by the same module family —
   sync is dead by omission, not by design.
2. The send path is dead: `ipfw_sync_send_state_prt` is assigned at
   MOD_LOAD (ip_fw3_sync.c:474) but has no caller anywhere in sys/.

So nothing can reach `ip_fw3_sync_send_state()` today. The defect
matters the moment anyone wires the pointer up (the module exists and
is shipped in /boot/kernel/ipfw3_basic.ko). This matches the LATENT
classification of the pass-1 findings DF-0700..DF-0706 for the same
file.

## Fix

`fix.diff` in this directory zeroes the struct before filling the three
intended fields.

## Verification

Code-level: certain (the initialization gap is directly visible at
ip_fw3_sync.c:443-452). Runtime: not reproducible — the code is dead
(see `VERDICT.md`); the on-guest check `df3452_dead.c` demonstrates the
sockopt no-op. No QEMU runtime verification is meaningful for
unreachable code; status `not_reproduced` with impact `none`
(latent). Per contract, Low/LATENT findings skip Phase V.
