DragonFlyBSD Kernel Audit
DF-0543 / hci_event_analysis.sh
← back to finding ↓ download raw
#!/bin/sh
# DF-0543 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_NUM_COMPL_PKTS (:171) -> num_compl_pkts (:878)
#
# num_compl_pkts pulls sizeof(ng_hci_num_compl_pkts_ep)=1 byte
# (num_con_handles) then loops while num_con_handles>0, consuming 4 bytes per
# entry (sizeof(h)=2 + sizeof(p)=2) and NEVER checking the mbuf length.
#
# A crafted HCI NUMBER_OF_COMPLETED_PACKETS event that triggers the bug:
#   byte 0    : 0x13   (event = NG_HCI_EVENT_NUM_COMPL_PKTS)
#   byte 1..2 : length = 0x0001  (HCI event "length" param, NOT enforced)
#   byte 3    : num_con_handles = 0xFF  (255 -- attacker controlled)
#   <no more data>
#
# num_compl_pkts m_adj(1) drops the num_con_handles byte, leaving 0 bytes. The
# first loop iter does m_copydata(event,0,2,&h). m_copydata
# (sys/kern/uipc_mbuf.c:1671) finds m->m_len == 0, 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 deref => page-fault
#    panic. (No copyout: parsed h/p only update an in-kernel counter -> DoS.)
#
# Per-entry consumption = sizeof(h)=2 + sizeof(p)=2 = 4
# Fix in fix.diff: stop when event->m_pkthdr.len < (sizeof(h)+sizeof(p)).
echo "DF-0543: source-level analysis only (netgraph7 BT not reachable on default guest)."
echo "See README.md / VERDICT.md / fix.diff."