# DF-3282 VERDICT — VERIFIED / reproduced / fixed

## Bottom line

**Reproduced: yes. Impact: panic (privileged local DoS). Status after fix: fixed.**

`ieee80211_beacon_update()` writes a newly-installed beacon application IE
to kernel address `0x0+ie_len` whenever the first app IE is installed on a
vap whose beacon was constructed without one. The root cause is pointer
arithmetic on a NULL `bo->bo_appie`:

* `sys/netproto/802_11/wlan/ieee80211_output.c:3215-3219` —
  `ieee80211_beacon_construct()` only records `bo->bo_appie` when
  `vap->iv_appie_beacon != NULL` at construct time (beacons are built once,
  at vap RUN).
* `sys/netproto/802_11/wlan/ieee80211_output.c:3599-3612` — on the first
  update after an app IE is installed (SIOCS80211 IEEE80211_IOC_APPIE,
  subtype BEACON — the standard hostapd/WPS beacon-IE plumbing), the code
  does `bo->bo_appie += adjust` with `bo->bo_appie == NULL` and then
  `add_appie()` memcpy's `ie_len` bytes to that address.

## How it was reproduced (stock INVARIENTS kernel, #0 Jul 2 06:02:54)

Harness: `fw.c` — a ~350-line software net80211 radio (KLD) that registers
`ieee80211com "fw0"`, supports hostap, allocates the beacon with
`ieee80211_beacon_alloc()` on RUN and services
`ieee80211_beacon_update()` from a 100 ms callout (real-driver discipline).
No wifi hardware needed.

```
kldload fw.ko
ifconfig wlan create wlandev fw0 wlanmode ap
ifconfig wlan0 ssid fwtest mode 11b channel 1 up
   -> "fw: wlan0 RUN, beacon allocated"        (beacon built, NO app IE)
./setappie wlan0                                (SIOCS80211 APPIE, 64B vendor IE)
   -> <=100 ms later:
Fatal trap 12: page fault while in kernel mode
fault virtual address = 0x40            <-- NULL + 64 (exactly the IE length)
fault code = supervisor write data, page not present
Stopped at memcpy+0x1c: movq %rdx,(%rdi)     <-- add_appie's memcpy
```

Full serial-console capture in `panic.txt`; command transcript in
`run.log`. Guest down after the fault (`vm.sh status` => down).

## Exploit chain

None beyond denial of service: the write address is `0x0+N` with
`N = ie_len ≤ 1024`, always inside the unmapped zero page on x86-64. It is
a hard kernel panic (CWE-476/682 family), not a controllable-corruption
primitive.

## Fix validation

`fix.diff` makes the update path handle the first-app-IE case explicitly:
the new IE occupies the space vacated at the head of the shifted trailer
and becomes part of the trailer (so later TIM resizes move it too).

* Baseline (stock kernel): panic within one beacon tick — see `panic.txt`.
* Patched (`patch -p1 < fix.diff` + `make nativekernel && make
  installkernel`, kernel #1 Sep 10 04:41): `setappie` succeeds, beacon
  keeps updating for 40+ ticks, guest stays up, `ifconfig wlan0 destroy` +
  `kldunload fw` complete cleanly.

`fix_status: fixed`, `fix_baseline_reproduced: 1`, `fix_patched_reproduced:
0` (the bug no longer manifests).

## Threat model notes

SIOCS80211 requires `SYSCAP_NONET_WIFI` (ieee80211_ioctl.c:3472) — root or
a capability-granted network-wifi manager (hostapd/wpa_supplicant run as
exactly this). The trigger ordering (beacon allocated before first app IE)
is the *common* case for an AP whose config daemon attaches WPS/interworking
IEs after the interface is already beaconing, and it is remotely inducible
in WPS deployments (the WPS state machine rewrites beacon IEs on
unauthenticated user interaction).

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
