# DF-4795 — ig_hal VF: uninitialized kernel-stack tail of the multicast mailbox message transmitted to the PF

File: `sys/dev/netif/ig_hal/e1000_vf.c` (pass 2)
Function: `e1000_update_mc_addr_list_vf()` — lines 400-437

## What happens

```c
u32 msgbuf[E1000_VFMAILBOX_SIZE];          /* :403 — never initialized */
u16 *hash_list = (u16 *)&msgbuf[1];
...
for (i = 0; i < mc_addr_count; i++)        /* :429-434 — writes count*2 bytes
                                               starting at byte 4            */
        hash_list[i] = hash_value & 0x0FFF;

e1000_write_msg_read_ack(hw, msgbuf, E1000_VFMAILBOX_SIZE);  /* :436 — 16 words */
```

`e1000_write_msg_read_ack` (:380-389) forwards all
`E1000_VFMAILBOX_SIZE`(16) words via `write_posted`, and
`e1000_write_mbx_vf` (`sys/dev/netif/ig_hal/e1000_mbx.c:476-477`) copies all
`size` words verbatim into the `E1000_VMBMEM` mailbox registers that the PF
(hypervisor / host OS) reads. With `mc_addr_count < 30`, the words past the
written hash entries — up to 50 of the 60 payload bytes for small counts,
e.g. count=5 → bytes 14..63 — are **uninitialized kernel stack** from the
guest, disclosed to the host-side PF driver. (The `|=` at :422 also reads
`msgbuf[0]` uninitialized before it is overwritten at :426 — dead value, no
transmit.)

Upstream FreeBSD initializes the buffer:
`u32 msgbuf[E1000_VFMAILBOX_SIZE] = {};` (cgit `sys/dev/e1000/e1000_vf.c`).

Threat model: the classic guest→host boundary. The recipient is the
PF driver in the more-privileged host, so this is a disclosure of guest
kernel stack residue across a privilege boundary that hostile-PF/VF
hardening (mxgpu/ena class) normally wants hermetic. Any unprivileged local
user in a guest can trigger it by joining multicast groups on an igb VF
interface (no privilege needed for group joins; `igb_set_multi()` →
`e1000_update_mc_addr_list` → this function).

## Reproduce (logic-level)

    cc -Wall -O2 -o mcmsg_demo mcmsg_demo.c && ./mcmsg_demo

Decisive line (deterministic byte-initialization model of the exact write
pattern):

    mc_addr_count=  5: ... uninit stack bytes sent to PF: 50 of 60

## Fix

`fix.diff` hunk 1 — `u32 msgbuf[E1000_VFMAILBOX_SIZE] = { 0 };` (git-apply
clean; compile-validated on the audit guest, build.log).

## Runtime PoC status

`untested` — the transmit requires an SR-IOV igb VF (audit guest is
virtio-only, see env.txt). The byte-level write/forward pattern is proven
from source; see VERDICT.md.
