DF-3282 / verdict.json
{ "finding_id": "DF-3282", "status": "reproduced", "reproduced": 1, "impact": "panic", "confidence": "certain", "verdict": "ieee80211_beacon_update() performs bo->bo_appie += adjust on a NULL bo->bo_appie when the first beacon app IE is installed after the beacon was constructed, then add_appie() memcpys the IE to kernel address 0x0+ie_len: guaranteed fatal page fault. Reproduced on the stock INVARIANTS guest with a software net80211 radio (fw.ko) + privileged SIOCS80211 APPIE ioctl: Fatal trap 12, fault virtual address = 0x40 (= NULL + 64-byte IE), supervisor write, Stopped at memcpy+0x1c, guest down within 100ms of the ioctl. fix.diff (first-app-IE lands in the vacated trailer head) validated by kernel rebuild: ioctl succeeds, beacon updates continue, vap destroy + kldunload clean, guest up.", "exploit_chain": "hostapd/WPS-style beacon app-IE install on a running AP whose beacon predates the first app IE (SIOCS80211 IEEE80211_IOC_APPIE subtype BEACON, SYSCAP_NONET_WIFI) -> next TBTT ieee80211_beacon_update() -> NULL+adjust pointer arithmetic -> memcpy to 0x40 -> page fault -> kernel panic (DoS). Write address is confined to the unmapped zero page, so no escalation beyond panic.", "evidence": [ "panic.txt (Fatal trap 12, fault VA 0x40, supervisor write, memcpy+0x1c)", "run.log (5-step transcript)", "fw.c (software ieee80211com with beacon_alloc/beacon_update callout)", "setappie.c (SIOCS80211 APPIE trigger)", "build.log (untrimmed KLD build)" ], "kernel_refs": [ "sys/netproto/802_11/wlan/ieee80211_output.c:3215", "sys/netproto/802_11/wlan/ieee80211_output.c:3591", "sys/netproto/802_11/wlan/ieee80211_output.c:3605", "sys/netproto/802_11/wlan/ieee80211_output.c:3612", "sys/netproto/802_11/wlan/ieee80211_ioctl.c:2346" ], "poc_changes": "Wrote the entire harness (no seed existed): fw.c fake-wifi KLD (net80211 radio with hostap + C_TXFRAG + beacon callout), setappie.c; fixed ioctl calling convention (SIOCS80211 takes ieee80211req directly, not ifreq.ifr_data), DFly ifconfig clone syntax (wlanmode ap), added driver nop callbacks the state machine calls.", "attempts": 3, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64 (baseline); patched #1: Thu Sep 10 04:41:20 UTC 2026", "runtime_sec": 5, "guest_dirty": 0, "build_cmd": "sh findings/poc/DF-3282/build.sh (make SYSDIR=/usr/src/sys in /root/fw; cc -O -o setappie setappie.c)", "run_cmd": "kldload /root/fw/fw.ko; ifconfig wlan create wlandev fw0 wlanmode ap; ifconfig wlan0 ssid fwtest mode 11b channel 1 up; /root/fw/setappie wlan0", "code_hash": "sha256 fw.c=87681503e55ec4780341b89f90c1f33243da3d34acc2df27746e005c14a5529f setappie.c=7b0a8ad9780c8970019be173dd83f26abc7e1369eb54a1c8e8193015057387fc", "notes": "Fix validation: baseline panic (kernel #0), patched kernel (#1 Sep 10 04:41:20, both DF-3282+DF-3283 fixes) -> no fault, beacon updates continue, clean destroy/unload. Guest reset with-src afterwards. Total verify cycle incl. two kernel builds ~75 min.", "recommended_fix": "In ieee80211_beacon_update()s APPIE block, handle bo_appie==NULL by placing the first app IE in the space vacated at the head of the shifted trailer (and fold it into bo_tim_trailer/len so TIM resizes track it) instead of doing pointer arithmetic on NULL.", "fix_status": "fixed", "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #1: Thu Sep 10 04:41:20 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "Patched kernel rebuilt in-guest (make nativekernel + installkernel) with fix.diff applied: the exact baseline trigger sequence now completes without any fault (beacon ticks continue 40+, vap destroy + kldunload clean, guest up). Baseline on stock kernel panicked within one beacon tick.", "fix_evidence": "Serial console before/after: panic.txt (baseline fault VA 0x40) vs run.log patched section + guest up status after both triggers; kernel build log /root/kernelbuild2.log in guest." } |