DF-0542 / hci_event_analysis.sh
#!/bin/sh # DF-0542 source-level reproduction analysis (NOT a runnable runtime trigger). # # The vulnerable code (sys/netgraph7/bluetooth/hci/ng_hci_evnt.c) is opt-in # (optional netgraph7_bluetooth), NOT compiled/shipped/loadable on the default # guest, so there is no live PoC. This file documents what a triggering HCI # event would look like and why it panics. # # Path: ng_hci_process_event (ng_hci_evnt.c:86) # -> case NG_HCI_EVENT_INQUIRY_RESULT (:127) -> inquiry_result (:370) # # inquiry_result pulls sizeof(ng_hci_inquiry_result_ep)=1 byte (num_responses) # then loops while num_responses>0, consuming 14 bytes per response and NEVER # checking the mbuf length. # # A crafted HCI INQUIRY_RESULT event that triggers the bug: # byte 0 : 0x02 (event = NG_HCI_EVENT_INQUIRY_RESULT) # byte 1..2 : length = 0x0001 (HCI event "length" param, NOT enforced) # byte 3 : num_responses = 0xFF (255 -- attacker controlled, 1st body byte) # <no more data> # # inquiry_result m_adj(1) drops the num_responses byte, leaving 0 bytes in the # chain. The first loop iter then does m_copydata(event,0,6,&bdaddr). m_copydata # (sys/kern/uipc_mbuf.c:1671) finds m->m_len == 0, sets m=m->m_next (NULL), and # the len>0 loop hits: # KASSERT(m != NULL, "%s: length > size of mbuf chain") # uipc_mbuf.c:1687 # => panic (INVARIANTS / GENERIC). Non-INVARIANTS => NULL m->m_len deref => # page-fault panic. Prior *mtod reads (:408,:414) leak stale mbuf residue # into the neighbor cache (in-kernel; limited). # # Per-response consumption = sizeof(bdaddr_t)=6 + 3*(u_int8_t)=3 + # NG_HCI_CLASS_SIZE=3 + sizeof(clock_offset)=2 = 14 # Fix in fix.diff: stop when event->m_pkthdr.len < NG_HCI_INQUIRY_RESULT_SIZE. echo "DF-0542: source-level analysis only (netgraph7 BT not reachable on default guest)." echo "See README.md / VERDICT.md / fix.diff." |